diff --git a/.codespell-whitelist b/.codespell-whitelist new file mode 100644 index 0000000000000..21c9c7e4ce907 --- /dev/null +++ b/.codespell-whitelist @@ -0,0 +1,7 @@ +uint +ith +mitre +readded +crate +developper +ist diff --git a/.travis-ci.sh b/.travis-ci.sh index f907ac4dbfc6a..98b6f81471edd 100755 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -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 diff --git a/.travis.yml b/.travis.yml index a4e1fb8857cc1..70b2fd191a57f 100644 --- a/.travis.yml +++ b/.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. @@ -29,6 +29,9 @@ matrix: env: TASK='htmlproofer-external' - rvm: 2.2.5 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 env: TASK='htmlproofer-external' diff --git a/EIPS/eip-1.md b/EIPS/eip-1.md index 8fc28d16cb96f..29fa8dd818b90 100644 --- a/EIPS/eip-1.md +++ b/EIPS/eip-1.md @@ -6,7 +6,7 @@ type: Meta author: Martin Becze , Hudson Jameson , and others https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md created: 2015-10-27 -updated: 2015-12-07, 2016-02-01, 2018-03-21, 2018-05-29, 2018-10-17 +updated: 2015-12-07, 2016-02-01, 2018-03-21, 2018-05-29, 2018-10-17, 2019-05-19 --- ## What is an EIP? @@ -23,23 +23,30 @@ 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 ([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 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. +: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 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. 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: @@ -67,6 +74,7 @@ Each status change is requested by the EIP author and reviewed by the EIP editor Other exceptional statuses include: * **Deferred** -- This is for core EIPs that have been put off for a future hard fork. +* **Abandoned** -- This EIP is no longer pursued by the original authors or it may not be a (technically) preferred option anymore. * **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 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. @@ -89,11 +97,11 @@ 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-X` (for eip **X**). When linking to an image in the EIP, use relative links such as `../assets/eip-X/image.png`. ## EIP Header Preamble -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:` (this is determined by the EIP editor) @@ -103,7 +111,7 @@ Each EIP must begin with an RFC 822 style header preamble, preceded and followed ` * discussions-to:` \ -` status:` +` status:` `* review-period-end:` @@ -169,7 +177,7 @@ The `created` header records the date that the EIP was assigned a number. Both h #### `updated` header -The `updated` header records the date(s) when the EIP was updated with "substantional" changes. This header is only valid for EIPs of Draft and Active status. +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 @@ -205,6 +213,10 @@ 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: @@ -241,6 +253,8 @@ 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 diff --git a/EIPS/eip-100.md b/EIPS/eip-100.md index f1ded40d3d19f..78b94002190eb 100644 --- a/EIPS/eip-100.md +++ b/EIPS/eip-100.md @@ -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 diff --git a/EIPS/eip-1011.md b/EIPS/eip-1011.md index 58b9264b87827..a35c0a7b6de81 100644 --- a/EIPS/eip-1011.md +++ b/EIPS/eip-1011.md @@ -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. diff --git a/EIPS/eip-1015.md b/EIPS/eip-1015.md index 4aecc15a1896e..0d690fa6ccc18 100644 --- a/EIPS/eip-1015.md +++ b/EIPS/eip-1015.md @@ -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,7 +24,7 @@ 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 @@ -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? diff --git a/EIPS/eip-1057.md b/EIPS/eip-1057.md index 41a27c9de9445..5ffc0b9f7d313 100644 --- a/EIPS/eip-1057.md +++ b/EIPS/eip-1057.md @@ -15,7 +15,7 @@ A new Proof-of-Work algorithm to replace Ethash that utilizes almost all parts o ## Abstract -ProgPoW is a proof-of-work algorithm designed to close the efficency gap available to specialized ASICs. It utilizes almost all parts of commodity hardware (GPUs), and comes pre-tuned for the most common hardware utilized in the Ethereum network. +ProgPoW is a proof-of-work algorithm designed to close the efficiency gap available to specialized ASICs. It utilizes almost all parts of commodity hardware (GPUs), and comes pre-tuned for the most common hardware utilized in the Ethereum network. ## Motivation @@ -53,7 +53,7 @@ With the growth of large mining pools, the control of hashing power has been del 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 specilized 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. +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 @@ -134,7 +134,7 @@ The random program changes every `PROGPOW_PERIOD` blocks to ensure the hardware Sample code is written in C++, this should be kept in mind when evaluating the code in the specification. -All numerics are computed using unsinged 32 bit integers. Any overflows are trimmed off before proceeding to the next computation. Languages that use numerics not fixed to bit lenghts (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. +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 vaiant of FNV1 for merging, but FNV1a provides better distribution properties. @@ -478,6 +478,7 @@ This algorithm is not backwards compatible with the existing Ethash, and will re ## Test Cases +### progpow 0.9.2 The algorithm run on block 30,000 produces the following digest and result: ``` header ffeeddccbbaa9988776655443322110000112233445566778899aabbccddeeff @@ -488,6 +489,8 @@ 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 @@ -496,4 +499,4 @@ The reference ProgPoW mining implementation located at [ProgPOW](https://github. 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/). -The reference ProgPoW mining implementation located at [ProgPOW](https://github.com/ifdefelse/ProgPOW) is a derivative of ethminer so retains the GPL license. \ No newline at end of file +The reference ProgPoW mining implementation located at [ProgPOW](https://github.com/ifdefelse/ProgPOW) is a derivative of ethminer so retains the GPL license. diff --git a/EIPS/eip-1066.md b/EIPS/eip-1066.md index bfb15d1d2ac90..6560b608a9c1e 100644 --- a/EIPS/eip-1066.md +++ b/EIPS/eip-1066.md @@ -7,7 +7,6 @@ status: Draft type: Standards Track category: ERC created: 2018-05-05 -version: 1.0.0 --- ## Simple Summary @@ -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] | @@ -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,7 +343,7 @@ 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] | @@ -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 2564 (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 2564 (4.3 billion) permutations. ### Multiple Returns diff --git a/EIPS/eip-107.md b/EIPS/eip-107.md index 48b13a0390b60..67caa48d96d45 100644 --- a/EIPS/eip-107.md +++ b/EIPS/eip-107.md @@ -1,7 +1,7 @@ --- eip: 107 title: safe "eth_sendTransaction" authorization via html popup -author: Ronan Sandford +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:, result:, error: } @@ -612,3 +612,6 @@ That's it. ``` +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1077.md b/EIPS/eip-1077.md index 81ff8f8b43275..bd509879b5473 100644 --- a/EIPS/eip-1077.md +++ b/EIPS/eip-1077.md @@ -1,7 +1,7 @@ --- eip: 1077 title: Executable Signed Messages refunded by the contract -author: Alex Van de Sande , Ricardo Guilherme Schmidt +author: Alex Van de Sande , 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 @@ -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) diff --git a/EIPS/eip-1078.md b/EIPS/eip-1078.md index f004566667cc6..990d446f833ce 100644 --- a/EIPS/eip-1078.md +++ b/EIPS/eip-1078.md @@ -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. diff --git a/EIPS/eip-1080.md b/EIPS/eip-1080.md index e5f7a46717772..18277e8fcba4a 100644 --- a/EIPS/eip-1080.md +++ b/EIPS/eip-1080.md @@ -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. diff --git a/EIPS/eip-1081.md b/EIPS/eip-1081.md index d5a7556c86db4..835ecac7edefd 100644 --- a/EIPS/eip-1081.md +++ b/EIPS/eip-1081.md @@ -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: diff --git a/EIPS/eip-1102.md b/EIPS/eip-1102.md index e5eaa74f28366..778e31026d984 100644 --- a/EIPS/eip-1102.md +++ b/EIPS/eip-1102.md @@ -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 @@ -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 @@ -100,20 +101,17 @@ try { ### Constraints -* Browsers **MUST** expose a provider at `window.ethereum`. -* Browsers **MUST NOT** populate the provider with user accounts by default. +* Browsers **MUST** expose a provider at `window.ethereum` . * 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 diff --git a/EIPS/eip-1108.md b/EIPS/eip-1108.md index c702d25e5f8f4..ce6438e3a6620 100644 --- a/EIPS/eip-1108.md +++ b/EIPS/eip-1108.md @@ -1,7 +1,8 @@ --- eip: 1108 title: Reduce alt_bn128 precompile gas costs -author: Antonio Salazar Cardozo (@shadowfiend) +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: Draft type: Standards Track category: Core @@ -9,14 +10,18 @@ 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[1] | 150 | | `ECMUL` | `0x07` | 40 000[1] | 6 000 | -| Pairing check | `0x08` | 80 000 * k + 100 000[2]| 28 300 * k + 35 450 | +| Pairing check | `0x08` | 80 000 * k + 100 000[2]| 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[3]. +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/). diff --git a/EIPS/eip-1109.md b/EIPS/eip-1109.md index 1d80f9101dc9b..647796a77479f 100644 --- a/EIPS/eip-1109.md +++ b/EIPS/eip-1109.md @@ -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. diff --git a/EIPS/eip-1123.md b/EIPS/eip-1123.md index 11605fcfebe02..aa0cf3170c52a 100644 --- a/EIPS/eip-1123.md +++ b/EIPS/eip-1123.md @@ -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 diff --git a/EIPS/eip-1154.md b/EIPS/eip-1154.md index a9fedf4d2e206..4e8dc483fdd13 100644 --- a/EIPS/eip-1154.md +++ b/EIPS/eip-1154.md @@ -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 diff --git a/EIPS/eip-1155.md b/EIPS/eip-1155.md index edda721eb36ca..a35e508c6070f 100644 --- a/EIPS/eip-1155.md +++ b/EIPS/eip-1155.md @@ -1,11 +1,10 @@ --- eip: 1155 title: ERC-1155 Multi Token Standard -author: Witek Radomski , Andrew Cooke , Philippe Castonguay , James Therien , Eric Binet +author: Witek Radomski , Andrew Cooke , Philippe Castonguay , James Therien , Eric Binet , Ronan Sandford type: Standards Track category: ERC -status: Draft -review-period-end: 2019-03-28 +status: Final created: 2018-06-17 discussions-to: https://github.com/ethereum/EIPs/issues/1155 requires: 165 @@ -13,28 +12,30 @@ 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 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. +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 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.7; +pragma solidity ^0.5.9; /** @title ERC-1155 Multi Token Standard @@ -43,84 +44,88 @@ pragma solidity ^0.5.7; */ 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 MUST be msg.sender. - When minting/creating tokens, the `_from` field MUST be set to `0x0` - When burning/destroying tokens, the `_to` field MUST be set to `0x0` - 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 MUST be msg.sender. - When minting/creating tokens, the `_from` field MUST be set to `0x0` - When burning/destroying tokens, the `_to` field MUST be set to `0x0` - 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 (i.e. balance for each (owner, id) pair) + @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); @@ -132,9 +137,9 @@ interface ERC1155 /* is ERC165 */ { */ function setApprovalForAll(address _operator, bool _approved) external; - /** + /** @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 */ @@ -144,58 +149,284 @@ interface ERC1155 /* is ERC165 */ { ### 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.7; +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 + @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 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)"))` */ function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) external returns(bytes4); - + /** @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 + @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 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)"))` */ - function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4); + function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4); } ``` +### Safe Transfer Rules + +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. + +#### Scenarios + +**_Scenario#1 :_** The recipient is not a contract. +* `onERC1155Received` and `onERC1155BatchReceived` MUST NOT be called on an EOA (Externally Owned Account). + +**_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. + +**_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 +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 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/{id}.json` would be replaced with `https://token-cdn-domain/780000000000001e000000000000000000000000000000000000000000000000.json` if the client is referring to token ID `780000000000001e000000000000000000000000000000000000000000000000`. +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. -The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: `[0-9a-f]` with no 0x prefix. +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 following optional extensions can be identified with the (ERC-165 Standard Interface Detection)[https://eips.ethereum.org/EIPS/eip-165]. +The optional `ERC1155Metadata_URI` extension can be identified with the (ERC-165 Standard Interface Detection)[https://eips.ethereum.org/EIPS/eip-165]. -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. +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.7; +pragma solidity ^0.5.9; /** Note: The ERC-165 identifier for this interface is 0x0e89341c. @@ -204,7 +435,7 @@ 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); @@ -215,7 +446,8 @@ interface ERC1155Metadata_URI { 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 { @@ -277,7 +509,7 @@ An example of an ERC-1155 Metadata JSON file follows. The properties array propo ##### Localization -Metadata localization should be standardized to increase presentation uniformity accross 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. +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 @@ -361,7 +593,10 @@ fr.json: ### Approval -The function `setApprovalForAll` allows an operator to manage one's entire set of tokens on behalf of the approver. To permit approval of a subset of token IDs, an interface such as [ERC-1761 Scoped Approval Interface (DRAFT)](https://eips.ethereum.org/EIPS/eip-1761) is suggested. +The function `setApprovalForAll` allows an operator to manage one's entire set of tokens on behalf of the approver. To permit approval of a subset of token IDs, an interface such as [ERC-1761 Scoped Approval Interface](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 @@ -391,52 +626,70 @@ As the Ethereum ecosystem continues to grow, many dapps are relying on tradition The function `setApprovalForAll` allows an operator to manage one's entire set of tokens on behalf of the approver. It enables frictionless interaction with exchange and trade contracts. -Restricting approval to a certain set of Token IDs, quantities or other rules MAY be done with an additional interface or an external contract. The rationale is to keep the ERC-1155 standard as generic as possible for all use-cases without imposing a specific approval scheme on implementations that may not need it. Standard token approval interfaces can be used, such as the suggested [ERC-1761 Scoped Approval Interface](https://github.com/ethereum/EIPs/issues/1761) which is compatible with ERC-1155. +Restricting approval to a certain set of token IDs, quantities or other rules MAY be done with an additional interface or an external contract. The rationale is to keep the ERC-1155 standard as generic as possible for all use-cases without imposing a specific approval scheme on implementations that may not need it. Standard token approval interfaces can be used, such as the suggested [ERC-1761 Scoped Approval Interface](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. +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. +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. +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. + +##### Split ID bits + +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. -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 ``. +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 ``. -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. +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 ``. If your implementation uses this technique this naturally means the index of a non-fungible SHOULD be 1-based. -### Example of split ID bits +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. ``` +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://eips.ethereum.org/EIPS/eip-721) - [ERC-165 Standard Interface Detection](https://eips.ethereum.org/EIPS/eip-165) -- [ERC-1538 Transparent Contract Standard (DRAFT)](https://eips.ethereum.org/EIPS/eip-1538) +- [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) @@ -452,6 +705,7 @@ balanceOf(baseToken + index, msg.sender); // Get balance of the Non-Fungible tok - [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/). diff --git a/EIPS/eip-1167.md b/EIPS/eip-1167.md index 4b35d0462aee2..30154b6ad146d 100644 --- a/EIPS/eip-1167.md +++ b/EIPS/eip-1167.md @@ -22,7 +22,7 @@ By standardizing on a known minimal bytecode redirect implementation, this stand ## Motivation -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 diff --git a/EIPS/eip-1186.md b/EIPS/eip-1186.md index 3398e5b5819bf..de6a7d0263a5f 100644 --- a/EIPS/eip-1186.md +++ b/EIPS/eip-1186.md @@ -7,6 +7,7 @@ status: Draft type: Standards Track category: Interface created: 2018-06-24 +requires: 1474 --- @@ -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 -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 diff --git a/EIPS/eip-1193.md b/EIPS/eip-1193.md index 26fd23fbf3b5f..06e387c57c61b 100644 --- a/EIPS/eip-1193.md +++ b/EIPS/eip-1193.md @@ -7,6 +7,7 @@ status: Draft type: Standards Track category: Interface created: 2018-06-30 +requires: 155, 695, 1102, 1474 --- ## Summary @@ -27,36 +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. See [EIP 1102: Opt-in account exposure](https://eips.ethereum.org/EIPS/eip-1102). - -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 enabled account(s) addresses. - ### Events Events are emitted using [EventEmitter](https://nodejs.org/api/events.html). #### notification -All subscriptions from the node emit on "subscription type" (e.g. `eth_subscription`, or `ssh_subscription`). Attach listeners with: +All subscriptions from the node emit on notification. Attach listeners with: ```js -ethereum.on('eth_subscription', listener: (result: any) => void): this; +ethereum.on('notification', listener: (result: any) => void): this; ``` -To create a subscription, call `ethereum.send('eth_subscribe')` or `ethereum.send('shh_subscribe')`. The subscription object will emit through the specifc subscription type. - -The result object will look as follows: - -```js -{ - "subscription":"0xc3b33aa549fb9a60e95d21862596617c", - "result": {...} -} -``` +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). @@ -85,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. @@ -112,6 +106,7 @@ const ethereum = window.ethereum; // A) Set provider in web3.js var web3 = new Web3(ethereum); +// web3.eth.getBlock('latest', true).then(...) // B) Use provider object directly @@ -128,26 +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 => { @@ -161,13 +137,13 @@ ethereum }); -// Example 4: Log new blocks +// Example 3: Log new blocks let subId; ethereum .send('eth_subscribe', ['newHeads']) .then(subscriptionId => { subId = subscriptionId; - ethereum.on('eth_subscription', result => { + ethereum.on('notification', result => { if (result.subscription === subscriptionId) { if (result.result instanceof Error) { const error = result.result; @@ -188,22 +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')}`); }; @@ -211,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}`); }); @@ -227,18 +190,6 @@ If an error occurs during processing, such as an HTTP error or internal parsing If the 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. - -For full specification of the `eth_requestAccounts` RPC method, see [EIP 1102: Opt-in account exposure](https://eips.ethereum.org/EIPS/eip-1102). - ### 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`. @@ -255,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`). diff --git a/EIPS/eip-1202.md b/EIPS/eip-1202.md index a114f2e2c09b5..5cec98bce71d8 100644 --- a/EIPS/eip-1202.md +++ b/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. @@ -135,19 +119,10 @@ We made the following design decisions and here are the rationales. * It's assumes for each individual address, they can only vote for one decision. They can distribute their available voting power into more granular level. If implementor wants allow this, they ask the user to create another wallet address and grant the new address certain power. For example, a token based voting where voting weight is determined by the amount of token held by a voter, a voter who wants to distribute its voting power in two different option(option set) can transfer some of the tokens to the new account and cast the votes from both accounts. - **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 @@ -258,39 +182,13 @@ Here are a few early questions I'd like to ask people here. - [Carbon Vote](http://carbonvote.com/) - [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)* +## Acknowledgement +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. -Your comments and suggestions will be greatly appreciated. +## Work Directory +The drafting and revision of EIP-1202 is conducted at [GitHub/xinbenlv/eip-1202](https://github.com/xinbenlv/eip-1202) -## Acknowledgement -The authors of EIP 1202 greatly appreciate the valuable input 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. - ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1261.md b/EIPS/eip-1261.md index 5645d025a99fd..132383e5eee99 100644 --- a/EIPS/eip-1261.md +++ b/EIPS/eip-1261.md @@ -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. @@ -43,7 +43,7 @@ Because a person is not necessitated to have EXACTLY one of the elements. He or ## Motivation -A standard interface allows any user,applications to work with any MVT on Ethereum. We provide for simple ERC-1261 smart contracts. Additional applications are discussed below. +A standard interface allows any user, applications to work with any MVT on Ethereum. We provide for simple ERC-1261 smart contracts. Additional applications are discussed below. This standard is inspired from the fact that voting on the blockchain is done with token balance weights. This has been greatly detrimental to the formation of flexible governance systems on the blockchain, despite the tremendous governance potential that blockchains offer. The idea was to create a permissioning system that allows organizations to vet people once into the organization on the blockchain, and then gain immense flexibility in the kind of governance that can be carried out. @@ -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 diff --git a/EIPS/eip-1271.md b/EIPS/eip-1271.md index 94b8551e61b93..a76c905d60896 100644 --- a/EIPS/eip-1271.md +++ b/EIPS/eip-1271.md @@ -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. diff --git a/EIPS/eip-1283.md b/EIPS/eip-1283.md index 7361bdd89eaf8..38df50bc111a0 100644 --- a/EIPS/eip-1283.md +++ b/EIPS/eip-1283.md @@ -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. diff --git a/EIPS/eip-1319.md b/EIPS/eip-1319.md index 21d42440a0fdb..e51788eefd4ee 100644 --- a/EIPS/eip-1319.md +++ b/EIPS/eip-1319.md @@ -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)); } @@ -114,21 +114,21 @@ The read API consists of a set of methods that allows tooling to extract all con function getAllPackageIds(uint offset, uint limit) public view returns ( bytes32[] packageIds, - uint offset + 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. @@ -144,7 +144,7 @@ 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); @@ -154,7 +154,7 @@ 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: diff --git a/EIPS/eip-1344.md b/EIPS/eip-1344.md index 57f89c653434b..c41f38881907c 100644 --- a/EIPS/eip-1344.md +++ b/EIPS/eip-1344.md @@ -5,6 +5,7 @@ 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: Last Call created: 2018-08-22 review-period-end: 2019-04-30 @@ -17,16 +18,20 @@ This EIP adds an opcode that returns the current chain's EIP-155 unique identifi [EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) proposes to use the chain ID to prevent replay attacks between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling signatures, especially for Layer 2 signature schemes using [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md). ## Specification -Adds a new opcode `CHAINID` at 0x46, which uses 0 stack arguments. It will push the current chain ID onto the stack. The operation costs `G_base` to execute. +Adds a new opcode `CHAINID` at 0x46, which uses 0 stack arguments. It pushes the current chain ID onto the stack. The operation costs `G_base` to execute. ## 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. +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. @@ -39,5 +44,8 @@ TBD ## Implementation A sample implementation was attempted here: https://github.com/fubuloubu/py-evm/commit/eaab5ffa2164d4cc06ae5c855a49d030965be828 +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/). diff --git a/EIPS/eip-1355.md b/EIPS/eip-1355.md index 3dbd4df3f61d1..0cf93798191cc 100644 --- a/EIPS/eip-1355.md +++ b/EIPS/eip-1355.md @@ -3,7 +3,7 @@ eip: 1355 title: Ethash 1a author: Paweł Bylica (@chfast) , Jean M. Cyr (@jean-m-cyr) discussions-to: https://ethereum-magicians.org/t/eip-1355-ethash-1a/1167 -status: Draft +status: Abandoned type: Standards Track category: Core created: 2018-08-26 diff --git a/EIPS/eip-1380.md b/EIPS/eip-1380.md index 87a29aadeda43..f8476e1f4673b 100644 --- a/EIPS/eip-1380.md +++ b/EIPS/eip-1380.md @@ -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 diff --git a/EIPS/eip-1388.md b/EIPS/eip-1388.md index 84c2f296702b8..6bf1ca4ec8bee 100644 --- a/EIPS/eip-1388.md +++ b/EIPS/eip-1388.md @@ -23,7 +23,7 @@ This ERC provides a smart contract interface for anyone to manage a list of atte ### Draft implementation ``` /* 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 { diff --git a/EIPS/eip-1417.md b/EIPS/eip-1417.md index 81f11a79e6cd3..f30735effc242 100644 --- a/EIPS/eip-1417.md +++ b/EIPS/eip-1417.md @@ -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[]); @@ -231,7 +231,7 @@ Having explained our rationale, we are looking forward to hearing from the commu **Gas and Complexity** (regarding the enumeration for proposal count) -This specification contemplates implementations that contain a sample of 32 proposals (max upto blockgaslimit). If your application is able to grow and needs more than 32 proposals, then avoid using for/while loops in your code. These indicate your contract may be unable to scale and gas costs will rise over time without bound +This specification contemplates implementations that contain a sample of 32 proposals (max up to blockgaslimit). If your application is able to grow and needs more than 32 proposals, then avoid using for/while loops in your code. These indicate your contract may be unable to scale and gas costs will rise over time without bound **Privacy** diff --git a/EIPS/eip-1418.md b/EIPS/eip-1418.md index 6289137a62550..398adaa3f87e0 100644 --- a/EIPS/eip-1418.md +++ b/EIPS/eip-1418.md @@ -1,7 +1,7 @@ --- eip: 1418 title: Blockchain Storage Rent Payment -author: William Entriken <@fulldecent> +author: William Entriken (@fulldecent) discussions-to: https://github.com/ethereum/EIPs/issues/1418 status: Draft type: Standards Track diff --git a/EIPS/eip-145.md b/EIPS/eip-145.md index e3cc659122ac5..55ae9c39cebce 100644 --- a/EIPS/eip-145.md +++ b/EIPS/eip-145.md @@ -1,7 +1,7 @@ --- eip: 145 title: Bitwise shifting instructions in EVM -author: Alex Beregszaszi (@axic), Paweł Bylica +author: Alex Beregszaszi (@axic), Paweł Bylica (@chfast) type: Standards Track category: Core status: Final @@ -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 diff --git a/EIPS/eip-1450.md b/EIPS/eip-1450.md index 1eeb19903971a..ddbb8ba157f4a 100644 --- a/EIPS/eip-1450.md +++ b/EIPS/eip-1450.md @@ -301,7 +301,7 @@ Investors may “lose” their credentials for a number of reasons: they simply If an Investor (or, say, the Investor’s heir) loses their credentials, the Investor must go through a notarized process to notify the RTA of the situation and supply a new Investor address. From there, the RTA can `mint` the “lost” securities to the new Investor address and `burnFrom` the old Investor address (because the RTA knows all Investors’ addresses). ## Rationale -The are currently no token standards that 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: diff --git a/EIPS/eip-1462.md b/EIPS/eip-1462.md index f2004d0adc106..59713317ba9d9 100644 --- a/EIPS/eip-1462.md +++ b/EIPS/eip-1462.md @@ -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. diff --git a/EIPS/eip-1470.md b/EIPS/eip-1470.md index bda13e61495b6..d6f9dffc24f45 100644 --- a/EIPS/eip-1470.md +++ b/EIPS/eip-1470.md @@ -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). diff --git a/EIPS/eip-1474.md b/EIPS/eip-1474.md index 8eefc1bf5d0f1..b3150e00828dc 100644 --- a/EIPS/eip-1474.md +++ b/EIPS/eip-1474.md @@ -82,6 +82,25 @@ Examples `Quantity` values: |0x0400|`invalid`|leading zeroes not allowed| |ff|`invalid`|values must be prefixed| +##### `Block Identifier` + +The RPC methods below take a default block identifier as a parameter. +- `eth_getBalance` +- `eth_getStorageAt` +- `eth_getTransactionCount` +- `eth_getCode` +- `eth_call` +- `eth_getProof` + +Since there is no way to clearly distinguish between a `Data` parameter and a `Quantity` parameter, [EIP-1898](eip-1898.md) provides a format to specify a block either using the block hash or block number. The block identifier is a JSON `object` with the following fields: + +|Property|Type|Description| +|-|-|-| +|`[blockNumber]`|{[`Quantity`](#quantity)}|The block in the canonical chain with this number| +|OR `[blockHash]`|{[`Data`](#data)}|The block uniquely identified by this hash. The `blockNumber` and `blockHash` properties are mutually exclusive; exactly one of them must be set.| +|`requireCanonical`|{`boolean`}|(optional) Whether or not to throw an error if the block is not in the canonical chain as described below. Only allowed in conjunction with the `blockHash` tag. Defaults to `false`.| + +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` and `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. ##### `Data` @@ -381,7 +400,7 @@ Executes a new message call immediately without submitting a transaction to the |#|Type|Description| |-|-|-| |1|{`object`}|@property {[`Data`](#data)} `[from]` - transaction sender
@property {[`Data`](#data)} `to` - transaction recipient or `null` if deploying a contract
@property {[`Quantity`](#quantity)} `[gas]` - gas provided for transaction execution
@property {[`Quantity`](#quantity)} `[gasPrice]` - price in wei of each gas used
@property {[`Quantity`](#quantity)} `[value]` - value in wei sent with this transaction
@property {[`Data`](#data)} `[data]` - contract code or a hashed method call with encoded args| -|2|{[`Quantity`](#quantity)\|`string`}|block number, or one of `"latest"`, `"earliest"` or `"pending"`| +|2|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `"latest"`, `"earliest"` or `"pending"`, or a block identifier as described in [`Block Identifier`](#block-identifier)| #### Returns @@ -547,7 +566,7 @@ Returns the balance of an address in wei |#|Type|Description| |-|-|-| |1|{[`Data`](#data)}|address to query for balance| -|2|{[`Quantity`](#quantity)\|`string`}|block number, or one of `"latest"`, `"earliest"` or `"pending"`| +|2|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `"latest"`, `"earliest"` or `"pending"`, or a block identifier as described in [`Block Identifier`](#block-identifier)| #### Returns @@ -818,7 +837,7 @@ Returns the contract code stored at a given address |#|Type|Description| |-|-|-| |1|{[`Data`](#data)}|address to query for code| -|2|{[`Quantity`](#quantity)\|`string`}|block number, or one of `"latest"`, `"earliest"` or `"pending"`| +|2|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `"latest"`, `"earliest"` or `"pending"`, or a block identifier as described in [`Block Identifier`](#block-identifier)| #### Returns @@ -1039,7 +1058,7 @@ Returns the value from a storage position at an address |-|-|-| |1|{[`Data`](#data)}|address of stored data| |2|{[`Quantity`](#quantity)}|index into stored data| -|3|{[`Quantity`](#quantity)\|`string`}|block number, or one of `"latest"`, `"earliest"` or `"pending"`| +|3|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `"latest"`, `"earliest"` or `"pending"`, or a block identifier as described in [`Block Identifier`](#block-identifier)| #### Returns @@ -1284,7 +1303,7 @@ Returns the number of transactions sent from an address |#|Type|Description| |-|-|-| |1|{[`Data`](#data)}|address to query for sent transactions| -|2|{[`Quantity`](#quantity)\|`string`}|block number, or one of `"latest"`, `"earliest"` or `"pending"`| +|2|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `"latest"`, `"earliest"` or `"pending"`, or a block identifier as described in [`Block Identifier`](#block-identifier)| #### Returns diff --git a/EIPS/eip-1484.md b/EIPS/eip-1484.md index 87d4340040b20..ebe60637774e6 100644 --- a/EIPS/eip-1484.md +++ b/EIPS/eip-1484.md @@ -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; diff --git a/EIPS/eip-1485.md b/EIPS/eip-1485.md index 716455caf8eca..9dbdbcb3ef811 100644 --- a/EIPS/eip-1485.md +++ b/EIPS/eip-1485.md @@ -1,7 +1,7 @@ --- eip: 1485 title: TEthashV1 -author: trustfarm (KT Ahn - 안씨아저씨) , , +author: trustfarm (KT Ahn - 안씨아저씨) , trustfarm discussions-to: https://ethereum-magicians.org/t/anti-eth-asic-mining-eip-1488-pr/1807 status: Draft type: Standards Track @@ -97,7 +97,7 @@ In TETHashV1, Adapts fully follow the FNV1A implementation. - TETHASHV1 FNV1A implementation -Followings are reference implementation of FNV1A adapted in TETHashV1. +Following are reference implementation of FNV1A adapted in TETHashV1. ```cpp // Reference Pseudo c/cpp implementation @@ -177,7 +177,7 @@ F(00,10)::VEC(0, 10, ffffffff, 0):: FNV :00000010, DF=0000001f(05) DS(00000 In case of ethash algorithm, it can't prevent ASIC forever. -And, current ethash algorithm's FNV function is depricated. +And, current ethash algorithm's FNV function is deprecated. So, It needs to be upgraded and it will make current ethash based ASICs obsolete. @@ -187,7 +187,7 @@ Another propose of big differencing the Ethash algorithm need to crypto analysis **Verification and Optimization timeline Examples** -orignal ethminer (2015) -> claymore optimized miner (2016) [1year] +original ethminer (2015) -> claymore optimized miner (2016) [1year] genoil ethminer (2015) -> ethereum-mining/ethminer (2017) [2year] diff --git a/EIPS/eip-1491.md b/EIPS/eip-1491.md index 3b9c9a645755c..66502ef07748b 100644 --- a/EIPS/eip-1491.md +++ b/EIPS/eip-1491.md @@ -18,7 +18,7 @@ A standard interface for Human Capital Accounting tokens. ## Abstract -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 @@ -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); @@ -457,66 +457,66 @@ 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 */ diff --git a/EIPS/eip-150.md b/EIPS/eip-150.md index 709ffaecdca59..c9bef1ed15210 100644 --- a/EIPS/eip-150.md +++ b/EIPS/eip-150.md @@ -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 diff --git a/EIPS/eip-1523.md b/EIPS/eip-1523.md new file mode 100644 index 0000000000000..31c2fef02c11b --- /dev/null +++ b/EIPS/eip-1523.md @@ -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 + +A standard interface for insurance policies, based on ERC 721. + +## Abstract + +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 + +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 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 + +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 + + +## Test Cases + + +## Implementation + + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-155.md b/EIPS/eip-155.md index 52324ad10820a..11efe541c5dc3 100644 --- a/EIPS/eip-155.md +++ b/EIPS/eip-155.md @@ -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 diff --git a/EIPS/eip-1559.md b/EIPS/eip-1559.md new file mode 100644 index 0000000000000..4dec83e889355 --- /dev/null +++ b/EIPS/eip-1559.md @@ -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 +--- + + + +## Simple Summary + +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 + +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 + +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 + +**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 + + + +## Implementation + + + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1571.md b/EIPS/eip-1571.md index fedc29b994b48..4979cfc8bd6d9 100644 --- a/EIPS/eip-1571.md +++ b/EIPS/eip-1571.md @@ -5,10 +5,9 @@ author: Andrea Lanfranchi (@AndreaLanfranchi) , 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" diff --git a/EIPS/eip-1577.md b/EIPS/eip-1577.md index bcd1467bae556..638c948660db5 100644 --- a/EIPS/eip-1577.md +++ b/EIPS/eip-1577.md @@ -102,7 +102,12 @@ In order to support names that have an IPFS or Swarm hash in their `content` fie ### 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) + +Moreover here is a [js implementation](https://github.com/pldespaigne/content-hash) to encode and decode `contenthash`. ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-158.md b/EIPS/eip-158.md index 70dcb4c356404..c5dbef191eaf8 100644 --- a/EIPS/eip-158.md +++ b/EIPS/eip-158.md @@ -4,7 +4,7 @@ title: State clearing author: Vitalik Buterin type: Standards Track category: Core -status: Replaced +status: Superseded created: 2016-10-16 superseded-by: 161 --- diff --git a/EIPS/eip-160.md b/EIPS/eip-160.md index 4749d89f45985..21a12dfef18bb 100644 --- a/EIPS/eip-160.md +++ b/EIPS/eip-160.md @@ -1,7 +1,7 @@ --- eip: 160 title: EXP cost increase -author: Vitalik Buterin +author: Vitalik Buterin (@vbuterin) type: Standards Track category: Core status: Final diff --git a/EIPS/eip-1613.md b/EIPS/eip-1613.md index 7ed7b64c2a6db..fdd4379b698cc 100644 --- a/EIPS/eip-1613.md +++ b/EIPS/eip-1613.md @@ -65,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 )` + Alternatively, dapps may use the balance sheet method for onboarding as well, by applying the methods suggested in the attacks/mitigations section below. +* 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: @@ -87,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](https://bit.ly/2EWWVN8) +![Sequence Diagram](http://bit.ly/2WZqM23) The process of registering/refreshing a `Relay`: @@ -95,12 +97,12 @@ 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's owner sends the required stake to `RelayHub` by calling `RelayHub.stake(address relay, uint unstake_delay)`. +* 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.register_relay(uint transaction_fee, string memory url)` with the relay's `transaction fee` (as a multiplier on transaction gas cost), and a URL for incoming transactions. +* 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 `transaction fee` in the relays map. -* `RelayHub` emits an event, `RelayAdded(Relay, owner, transaction_fee, relay_stake, unstake_delay, url)`. +* `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. @@ -119,8 +121,8 @@ The process of sending a relayed transaction: * `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. @@ -142,34 +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`. - * 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. @@ -216,8 +218,8 @@ 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. @@ -225,15 +227,15 @@ Scaling such attack would be prohibitively expensive, and actually quite profita ##### 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 indefinately. In order to mitigate that, the sender includes a `max_nonce` parameter with it's signing request. +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 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: 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. @@ -249,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, diff --git a/EIPS/eip-1616.md b/EIPS/eip-1616.md index c709dd104ccb2..c22cdec233d9a 100644 --- a/EIPS/eip-1616.md +++ b/EIPS/eip-1616.md @@ -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 @@ -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 { diff --git a/EIPS/eip-162.md b/EIPS/eip-162.md index 60cec465991f9..eaefc623561a1 100644 --- a/EIPS/eip-162.md +++ b/EIPS/eip-162.md @@ -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. @@ -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/). diff --git a/EIPS/eip-165.md b/EIPS/eip-165.md index 5d333aab4f91e..b930acbcc045d 100644 --- a/EIPS/eip-165.md +++ b/EIPS/eip-165.md @@ -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/). diff --git a/EIPS/eip-1679.md b/EIPS/eip-1679.md index 5236fb8407328..478926d3d02ad 100644 --- a/EIPS/eip-1679.md +++ b/EIPS/eip-1679.md @@ -2,6 +2,7 @@ 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 @@ -16,11 +17,70 @@ This meta-EIP specifies the changes included in the Ethereum hardfork named Ista - Codename: Istanbul - Activation: TBD -- Included EIPs: TBD + +### Included EIPs + +- TBD + +### Accepted EIPs + +- TBD + +### Rejected EIPs + +- TBD + +### Proposed EIPs + +- [EIP-615](https://eips.ethereum.org/EIPS/eip-615): Subroutines and Static Jumps for the EVM +- [EIP-663](https://eips.ethereum.org/EIPS/eip-663): Unlimited SWAP and DUP instructions +- [EIP-1057](https://eips.ethereum.org/EIPS/eip-1057): ProgPoW, a Programmatic + Proof-of-Work + - There is a + [pending audit](https://medium.com/ethereum-cat-herders/progpow-audit-goals-expectations-75bb902a1f01), + above and beyond standard security considerations, that should be evaluated + prior to inclusion. +- [EIP-1108](https://eips.ethereum.org/EIPS/eip-1108): Reduce alt_bn128 precompile gas costs +- [EIP-1109](https://eips.ethereum.org/EIPS/eip-1109): PRECOMPILEDCALL opcode (Remove CALL costs for precompiled contracts) + - requirement of EIP-1962 +- [EIP-1283](https://eips.ethereum.org/EIPS/eip-1283): Net gas metering for SSTORE without dirty maps +- [EIP-1344](https://eips.ethereum.org/EIPS/eip-1344): Add ChainID opcode +- [EIP-1352](https://eips.ethereum.org/EIPS/eip-1352): Specify restricted address range for precompiles/system contracts +- [EIP-1380](https://eips.ethereum.org/EIPS/eip-1380): Reduced gas cost for call to self +- [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559): Fee market change for ETH 1.0 chain +- [EIP-1965](https://eips.ethereum.org/EIPS/eip-1965): Method to check if a chainID is valid at a specific block Number +- [EIP-1702](https://eips.ethereum.org/EIPS/eip-1702): Generalized account versioning scheme +- [EIP-1706](https://eips.ethereum.org/EIPS/eip-1706): Disable SSTORE with gasleft lower than call stipend +- [EIP-1803](https://eips.ethereum.org/EIPS/eip-1803): Rename opcodes for clarity +- [EIP-1829](https://eips.ethereum.org/EIPS/eip-1829): Precompile for Elliptic Curve Linear Combinations +- [EIP-1884](https://eips.ethereum.org/EIPS/eip-1884): Repricing for trie-size-dependent opcodes +- [EIP-1930](https://eips.ethereum.org/EIPS/eip-1930): CALLs with strict gas semantic. Revert if not enough gas available. +- [EIP-1985](https://eips.ethereum.org/EIPS/eip-1985): Sane limits for certain EVM parameters +- [EIP-1959](https://eips.ethereum.org/EIPS/eip-1959): New Opcode to check if a chainID is part of the history of chainIDs +- [EIP-1962](https://eips.ethereum.org/EIPS/eip-1962): EC arithmetic and pairings with runtime definitions + - replaces EIP-1829 +- [EIP-2014](https://eips.ethereum.org/EIPS/eip-2014): Extended State Oracle +- [EIP-2025](https://eips.ethereum.org/EIPS/eip-2025): Funding Eth1.x with Developer Block Rewards +- [EIP-2026](https://eips.ethereum.org/EIPS/eip-2026): State Rent H - Fixed Prepayment for accounts +- [EIP-2027](https://eips.ethereum.org/EIPS/eip-2027): State Rent C - Net contract size accounting +- [EIP-2028](https://eips.ethereum.org/EIPS/eip-2028): Calldata gas cost reduction +- [EIP-2029](https://eips.ethereum.org/EIPS/eip-2029): State Rent A - State counters contract + - requirement of EIP-2031 +- [EIP-2031](https://eips.ethereum.org/EIPS/eip-2031): State Rent B - Net transaction counter +- [EIP-2035](https://eips.ethereum.org/EIPS/eip-2035): Stateless Clients - Repricing SLOAD and SSTORE to pay for block proofs +- [EIP-2045](https://eips.ethereum.org/EIPS/eip-2045): Particle gas costs for EVM opcodes +- [EIP-2046](https://eips.ethereum.org/EIPS/eip-2046): Reduced gas cost for static calls made to precompiles + +## Timeline + +* 2019-05-17 (Fri) hard deadline to accept proposals for "Istanbul" +* 2019-07-19 (Fri) soft deadline for major client implementations +* 2019-08-14 (Wed) projected date for testnet network upgrade (Ropsten, Görli, or ad-hoc testnet) +* 2019-10-16 (Wed) projected date for mainnet upgrade ("Istanbul") ## References -TBA +- [Core Dev call notes](https://github.com/ethereum/pm/issues/66#issuecomment-450840440) where timeline was proposed and accepted ## Copyright diff --git a/EIPS/eip-1681.md b/EIPS/eip-1681.md index 2e557f28cbf73..28c6b2fca4a72 100644 --- a/EIPS/eip-1681.md +++ b/EIPS/eip-1681.md @@ -51,7 +51,7 @@ For the dust-account clearing usecase, - 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, requireing one more journalled field. + - 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 diff --git a/EIPS/eip-170.md b/EIPS/eip-170.md index 5fd1b3d99397f..4f96551984122 100644 --- a/EIPS/eip-170.md +++ b/EIPS/eip-170.md @@ -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 diff --git a/EIPS/eip-1702.md b/EIPS/eip-1702.md index 1dc088d2a76f9..f2b7501b12d38 100644 --- a/EIPS/eip-1702.md +++ b/EIPS/eip-1702.md @@ -43,11 +43,31 @@ might still be a good idea. 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 integer. When -`version` is zero, the account is RLP-encoded with the first 4 +`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 @@ -58,32 +78,12 @@ 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 calling `address`. - -#### Alternative Design - -This provides an alternative design that allows `CREATE`, `CREATE2` -and contract creation transaction to deploy contract whose version are -different. - -The client maintains a mapping `V` of currently supported version -prefix (for example, `\0asm`) to `version` number. All version -prefixes have the invariant that given any prefix in mapping `a` and -`b`, `a` is not `b`'s prefix. Version numbers in `V` cannot be zero. - -Apply the following cause on contract deployment for all `CREATE`, -`CREATE2` and contract deployment transaction. +same `version` as the *code's version*. -* If the `version` of caller (determined by `I_a`) is zero, then - `CREATE` and `CREATE2` will always deploy contract with version zero. -* If the `version` of caller (determined by `I_a`) is not zero, do the - following checks and operations, and return out-of-gas if any of it - fails: - * Check that the code starts with an prefix in `V`, with `version` - number. - * Use `version`'s validation procedure to validate the *whole* code - (with prefix). - * Deploy the contract with `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 @@ -96,31 +96,14 @@ that has to be passed. If the validation phrase fails, deployment does not proceed and return out-of-gas. -### Contract Execution - -VM version used in contract execution is determined via calling -`address` (`I_a` in yellow paper). - ### 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`. Before a contract creation transaction is executed, -run *validation* on the contract creation code. If it does not pass, -return out-of-gas. - -#### Alternative Design - -This provides an alternative design that allows contract to be created -in multiple versions. - -Add an additional field `version` (256-bit integer) in contract -creation transaction. So it becomes `nonce`, `gasprice`, `startgas`, -`to`, `value`, `data`, `v`, `r`, `s`, `version`. When signing or -recovering, sign ten items, with `v`, `r`, `s` as defined by EIP-155. - -The transaction would be executed in `version` supplied. If `version` -is not supported or *validation* does not pass, return out-of-gas. +`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 @@ -130,23 +113,82 @@ Precompiled contracts and externally-owned addresses do not have 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 EIPs 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 EIP is also included. + +- [EIP-2138: Account Versioning Extension for Contract Creation + Transaction](https://github.com/ethereum/EIPs/pull/2138) +- [EIP-2139: Account Versioning Extension for CREATE and + CREATE2](https://github.com/ethereum/EIPs/pull/2139) + +## Usage Template + +This section defines how other EIPs might use this account versioning +EIP. Note that currently we only define the usage template for base +layer. + +Account versioning is usually applied directly to a hard fork meta +EIP. EIPs 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 includes EIPs 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 first 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 requires alternative design in contract -creation transaction section - -The second design above requires new versions of VMs follow a -formatting -- that it always has a prefix. In this way, the version -can be derived from the prefix, thus allowing a contract *family* to -have multiple versions. It also makes it so that we can pin contract -creation transaction using only one VM version, and it can deploy -other VM versions. +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 EIP-2138 and +EIP-2139. Alternatively, account versioning can also be done through: @@ -171,7 +213,7 @@ change how current contracts are executed. ### Performance Currently nearly all full node implementations uses config parameters -to decide which virtual machine version to use. Switching vitual +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. @@ -186,3 +228,7 @@ defined as above. ## Test Cases and Implementations To be added. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1710.md b/EIPS/eip-1710.md new file mode 100644 index 0000000000000..876910ae7be2d --- /dev/null +++ b/EIPS/eip-1710.md @@ -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 +--- + + + +## Simple Summary + +A standard way of representing web3 browser URLs for decentralized applications. + +## Abstract + + +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 + + +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 + + + +### 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 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/). diff --git a/EIPS/eip-1753.md b/EIPS/eip-1753.md new file mode 100644 index 0000000000000..16e20a1031624 --- /dev/null +++ b/EIPS/eip-1753.md @@ -0,0 +1,248 @@ +--- +eip: 1753 +title: Smart Contract Interface for Licences +author: Lucas Cullen (@BitcoinBrisbane), Kai Yeung (@CivicKai), Anna Crowley , Caroline Marshall , Katrina Donaghy +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 +``` +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/). diff --git a/EIPS/eip-1775.md b/EIPS/eip-1775.md new file mode 100644 index 0000000000000..8aa747219a230 --- /dev/null +++ b/EIPS/eip-1775.md @@ -0,0 +1,634 @@ +--- +eip: 1775 +title: App Keys, application specific wallet accounts +author: Vincent Eli (@Bunjin), Dan Finlay (@DanFinlay) +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 +requires: 137 +--- + + +## Simple Summary + + +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 + +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 the accounts along an Hierarchical Deterministic (HD) path restricted for the domain and we finally define an API for applications to derive and use these app keys. This ERC aims at finding a standard that will fit the needs of wallets and application developers while also allowing app keys to be used across wallets and yield the same accounts for the user for each application. + +## Motivation + +Wallets developers have agreed on an HD derivation path for ethereum accounts using BIP32, BIP44, SLIP44, [(see the discussion here)](https://github.com/ethereum/EIPs/issues/84). Web3 wallets have implemented in a roughly similar way the rpc eth api. [EIP1102](https://eips.ethereum.org/EIPS/eip-1102) introduced privacy through non automatic opt-in of a wallet account into an app increasing privacy. + +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 + + +### Applications + +An app is a website (or other) that would like to request from a wallet to access app keys. It can be any form of cryptography/identity relying application, ethereum but not only. + +Once connected to a wallet, an application can request to access a set of accounts derived exclusively for that application using the hierarchical deterministic (HD) paths. + +### Applications' HD path + +Using the BIP32 and BIP43 standards, we propose to use the following HD path for each app keys: + +`m / [standardized Path Beginning]' / [persona path]' / [application uniquely assigned path]' / [app's custom subpath]` + +Where: + +`standardized HD Path Beginning` is based on the EIP number that will be assigned to this EIP and we harden it. We use a different path than 44' since it's not bip44 compliant. At this point, I'm not sure if there is a list of BIP43 codes of standards following the `purpose` field specification of [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki). + +`persona path` allows to use applications with different and isolated personas (or in other words accounts) that are tracable by the application. They will still be fully restorable from the same mnemonic. + +`application uniquely assigned path` isolate each application along unique branches of the tree through these unique subPath combination. + +`app's custom subPath` give freedom to application to use this BIP32 compliant subPath to manage accounts and other needed parameters. + +Note that we suggest that each of these indexes, except those belonging to the app's custom subpath, must be hardened to fully isolate the public keys across personas and applications. + +### Standardized HD Path Beginning + +For the path header, several alternative are possible depending on what the cryptocommunities agree upon. + +The least contentious is the following one (as suggested [here in the BIP repository](https://github.com/bitcoin/bips/pull/523)): + +` 43' / 60' / 1775 ' ` + +However, there may be benefits to use only one depth instead of 3. We could use the `EIP Number'` (ie. 1775) or a ` BIP Number'` if we attain some cross crypto agreement that would avoid collision. + + +### Personas + +We allow the user to use different personas in combination to her mnemonic to potentially 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 personnas indexes. The app or domain, will not be aware that it is the same person and mnemonic behind both. + +We use a string following BIP32 format (can be hardened) to define personas. +The indexes should be hex under 0x80000000, 31 bits. + +E.g. `0'` or `0'/1/2'/0` or `1d7b'/a41c'` + +### Applications' Unique Identifiers + +#### Applications Names + +We need a way to uniquely identify each application. We will use a naming and a hashing scheme. + +In our favored spec, each application is uniquely defined and authenticated by its name, a domain string. It can be a Domain Name Service DNS name or and Ethereum Name Service ENS name. + +There are a few restrictions however on the characters used and normalisation, each name should be passed through the [NamePrep Algorithm](https://tools.ietf.org/html/rfc3491) + +In addition there must be a maximum size to the domain string that we need to determine such that the mapping from strings to nodes remains injective, to avoid collision. + +We recommend this standard to be following the [ENS Specs](http://docs.ens.domains/en/latest/implementers.html#namehash), reproduced below for convenience and reference. + +``` +Normalising and validating names +Before a name can be converted to a node hash using Namehash, the name must first be normalised and checked for validity - for instance, converting fOO.eth into foo.eth, and prohibiting names containing forbidden characters such as underscores. It is crucial that all applications follow the same set of rules for normalisation and validation, as otherwise two users entering the same name on different systems may resolve the same human-readable name into two different ENS names. +``` + +#### Hashing and Applications UIDs + +The ENS uses an hashing scheme to associate a domain to a unique hash, `node`, through the `namehash` function. We will use this hashing scheme both for ENS and for DNS names. + +This gives an unique identifier (UID) of 32 bytes. + +``` +e.g. for foo.bar.eth +app's uid 0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3 +``` + +For reference, here are the specs of ENS: + +``` +domain - the complete, human-readable form of a name; eg, ‘vitalik.wallet.eth’. +label - a single component of a domain; eg, ‘vitalik’, ‘wallet’, or ‘eth’. A label may not contain a period (‘.’). +label hash - the output of the keccak-256 function applied to a label; eg, keccak256(‘eth’) = 0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0. +node - the output of the namehash function, used to uniquely identify a name in ENS. +Algorithm +First, a domain is divided into labels by splitting on periods (‘.’). So, ‘vitalik.wallet.eth’ becomes the list [‘vitalik’, ‘wallet’, ‘eth’]. + +The namehash function is then defined recursively as follows: + +namehash([]) = 0x0000000000000000000000000000000000000000000000000000000000000000 +namehash([label, …]) = keccak256(namehash(…), keccak256(label)) + +keccak256(‘eth’) = 0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0 + +``` + +We thus propose to use the node of each app's domain as a unique identifier for each app but one can think of other UIDs, we include some alternative specs in the [Rationale](#Rationale) section below. + +### Applications' authentication + +If the application is using a DNS name then we simply authenticate the application by using the url of the loaded browser webpage. + +For applications using ENS, we can authenticate the application through ENS resolution. +The ENS can also allow to register and resolve metadata for the application such as `url`, and other parameters. + +If we use for instance this resolver profile defined in [EIP634](https://eips.ethereum.org/EIPS/eip-634) which permits the lookup of arbitrary key-value text data, we can for instance use the key `url` to point to a website. + +``` +A new resolver interface is defined, consisting of the following method: + +function text(bytes32 node, string key) constant returns (string text); +The interface ID of this interface is 0x59d1d43c. + +The text data may be any arbitrary UTF-8 string. If the key is not present, the empty string must be returned. +``` + +One can think of other authentication methods and even use some of them alongside the url-resolution method through ENS. We mention other methods in the [Rationale](#Rationale) section. + +We suggest for instance to also add an `authorEthAddress` text metadata field that can be used to authenticate messages from the application, with for instance a sign challenge. + +### Applications UID decomposition to get a BIP32 HD path + +Since each child index in an HD path only has 31 bits we will decompose the domain's hash as several child indexes, first as hex bytes then parsed as integers. + +For the applications's uid we use an `ENS namehash node` of 32 bytes, 256 bits (removing the leading `0x`). + +e.g. `foo.bar.eth` which gives the following namehash node: `0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3` + +We can decompose it in several ways, here are 2 potential ways: + +* First approach could favor having the least indexes: + +This requires to first convert the hex uid to 256 bits then decompose it as 8 * 31 bits + 8 bits + +``` +x = x0 || x1 || x2 || x3 || x4 || x5 || x6 || x7 || x8 +``` +where `x0` to `x7` are 31 bits and `x8` is 8 bits + +then we convert the `x_i` to uints. + +The derivation sub-path would be: +`x0'/x1'/x2'/x3'/x4'/x5'/x6'/x7'/x8'` + + +``` +E.g. + +foo.bar.eth + + +0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3 + +converted to binary (256 bits) + +6033644d673b +011000000011001101100100010011010110011100111011 +47b3bea04e79 +010001111011001110111110101000000100111001111001 +bbe06d78ce76 +101110111110000001101101011110001100111001110110 +b8be2fb8704f +101110001011111000101111101110000111000001001111 +9c2a80fd139c +100111000010101010000000111111010001001110011100 +81d3 +1000000111010011 + +256 bits: +0110000000110011011001000100110101100111001110110100011110110011101111101010000001001110011110011011101111100000011011010111100011001110011101101011100010111110001011111011100001110000010011111001110000101010100000001111110100010011100111001000000111010011 + +converted to less than or equal to 31 bits indexes: + +8 * 31 bits + 1 * 8 bits + +0110000000110011011001000100110 +1011001110011101101000111101100 +1110111110101000000100111001111 +0011011101111100000011011010111 +1000110011100111011010111000101 +1111000101111101110000111000001 +0011111001110000101010100000001 +1111101000100111001110010000001 +11010011 + +and converted to uints + +806990374'/1506726380'/2010384847'/465438423'/1181988293'/2025775553'/523785473'/2098437249'/211' + + +``` + + +* Second approach favors an homogeneous decomposition: + +Equal length indexes would be 16 * 16 bits or in other words 16 * 2 bytes, cleanest and favored spec: + +``` +x = x0 || x1 || x2 || x3 || x4 || x5 || x6 || x7 || x8 || x9 || x10 || x11 || x12 || x13 || x14 || x15 + +where || is concatenation +``` + + +``` +E.g. + +foo.bar.eth +0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3 +6033 644d 673b 47b3 bea0 4e79 bbe0 6d78 ce76 b8be 2fb8 704f 9c2a 80fd 139c 81d3 +6033'/644d'/673b'/47b3'/bea0'/4e79'/bbe0'/6d78'/ce76'/b8be'/2fb8'/704f'/9c2a'/80fd'/139c'/81d3' +24627'/25677'/26427'/18355'/48800'/20089'/48096'/28024'/52854'/47294'/12216'/28751'/39978'/33021'/5020'/33235' +``` + + +Between these 2 decomposition approaches, there is a trade-off between computational efficiency (having less depth) and having an homegenous decomposition. We tend to favor the first approach with least indexes. + + +### Application customisable HD sub path + +Finally, the last part of the hd path is under the application's control. This will allow applications developers to use the HD path structure that best fits their needs. Developers can for instance, among any combination of other parameters they like, choose to include a `version` field if they would like to use different signing accounts when updating to a new version. They can then also manage the user accounts in the way they would like, for instance including or not an index for `sets of accounts` (called `accounts` in BIP44), an index for `change` and an index for `account` (called `address_index` in BIP44). +We consider that a given child on the HD tree should be called an `account` and not an `address` since it is composed of a private key, a public key and an address. + +Similarly to the persona path, this sub path must follow bip32, with hex under 0x80000000, 31 bits. +It can be hardened depending on each application's needs and can be written as hex or unsigned integers. +It can include a large number of indexes. + +Q [Should we set a limit on the persona and application customsable hd path number of indexes?] + +### Example HD paths for app keys: + +``` +Dummy data: +EIP Number: 1775 +personaPath: 0'/712' +application's name: foo.bar.eth +uid: 0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3 +app custom path params: app_version, set_of_accounts_index, account_index +``` + +`m/43'/60'/1775'/0'/712'/806990374'/1506726380'/2010384847'/465438423'/1181988293'/2025775553'/523785473'/2098437249'/211'/0'/0'/0` + +## API: + +We propose to introduce new RPC methods but they should be restricted and wrapped such that some parameters (e.g. domain name) are imposed by the wallet on the caller depending on the caller's authentication. + +[TBD] Specify scope of RPC methods (some params should be forced to the authenticated domain value) and how to integrate them into web3 api. + +### App keys exposure: + +* `wallet.appkey.enable(options)` +This method allows to enable app keys (getting user permission to use and allow him to select the persona she would like to use). + +[TBD] Could return the account public key from the HD path before `the app's custom subPath`. Hence from this app's root account, one could derive all non hardened children public keys of the app's keys. + +[TBD] where `options` is a javascript object containing the permissions requested for these app keys. +Options could also include a challenge to be signed by the app's root account (would serve as authentication of the users from the app's perspective). The signature should then be also returned. + +Options should also include a parameter for the application to indicate which name should be used to compute the domain's HD path. That's required for applications that are loaded through ENS. They could be authenticated either through ENS or through DNS. These applications may like to use the DNS name even when they are resolved through ENS. (e.g. an application that just upgraded to ENS may like to continue using DNS paths to be retro-compatible for its former users). + +Uses the persona selected by the user (not known nor controllable by application). + +Uses the domain ens namehash (node) that was resolved to load window (not provided by application itself) + +### Ethereum accounts methods: + +* `appKey_eth_getPublicKey(hdSubPath) returns publicKey 64 bytes`: + +`hdSubPath` string with BIP32 format, "index_i / index_(i+1) '", can use hardening + +`publicKey` returns e.g. 0x80b994e25fb98f69518b1a03e59ddf4494a1a86cc66019131a732ff4a85108fbb86491e2bc423b2cdf6f1f0f4468ec73db0535a1528ca192d975116899289a4b + +* `appKey_eth_getAddress(hdSubPath) returns address 20 bytes`: + +`hdSubPath`: string with BIP32 format, "index_i / index_(i+1) '", can use hardening + +`address` e.g. 0x9df77328a2515c6d529bae90edf3d501eaaa268e + +* `appKey_eth_derivePublicKeyFromParent(parentPublicKey, hdSubPath) returns publicKey 64 bytes` + +`hdSubPath`: string with BIP32 format, "index_i / index_(i+1) '", should not use hardening here. + +* `appKey_eth_getAddressForPublicKey(publicKey) returns address 20 bytes` + +`publicKey` 64 bytes + +### Ethereum signing methods: + +* `appKey_eth_signTransaction(fromAddress, tx)` +tx is ethereum-js tx object + +* `appKey_eth_sign(fromAddress, message)` +* `appKey_eth_personalSign(fromAddress, message)` +* `appKey_eth_signTypedMessage(fromAddress, message)` +EIP712 + +### Ethereum broadcasting methods: + +* `appKey_eth_broadcastTransaction(tx, signedTx)` +tx is ethereum-js tx object + + +### Other potential methods: + +#### Other cryptocurrencies: +We defined for now Ethereum accounts and signing methods. However, one could do the same for other cryptocurrencies deriving accounts along their standards. This may open to some very interesting cross-blockchains application designs. + +#### Other cryptographic methods: +Similarly, using entropy provided by the HD Path, one could think of other cryptographic methods such as encryption and also other curve types. + + +#### Storage: +The HD path for each application can also be used as a key to isolate databases for user's persistent data. We could introduce methods that allow to read and write in a database specific to the application. + +Q [Benefit of this compared to using classical browser local storage?] + +### API permissions and confirmations from users: + +#### Initial permission request and full access afterwards: + +Each wallet has freedom in the way they implement their permission system along with this EIP and this API. We tend to favor a design where the applications would request once and for all full access to the applications keys (for their domain) and that the user has to confirm this once. From then on, any account derivation or signing for those applications keys will not prompt a confirmation request on the wallet side. +However applications themselves are free to reproduce some confirmation at their own level if they would like the users to double check the transactions or signatures they are making at the application level. This will be of course dependent on trusting the application code. + +#### Paranoia mode: +However, we would like to give users the option to monitor at any point applications keys and how applications user them. We therefore encourage wallets to introduce a `paranoia mode` that users can activate (for instance in the wallet advanced settings) to force confirmations request for all the applications keys actions. + +## Rationale + +### Isolated paths but customisable +The proposed specifications permit to have isolation between personas and between applications. Each persona / application combination will yield a unique subtree that can be explored by the application using the structure it would like to use. + +Personas are known only by the user and its wallet, application' UID based path is computable by everyone from the application's name. And then the application decides and communicates the final levels of the path. + +Only the wallet and the user will know the full tree and where we are in the tree (depth, parents). Applications will have knowledge only of the subtree, starting after the persona. + + +### API not exposing private keys + +Applications can derive accounts and request signing from them but they will not get access to the private keys of these accounts. So when the user closes her wallet entirely, the application can not continue signing for the user. This is of course in order to keep an user's ultimate control over its accounts. + +If there is a strong demand, we could add a method that exposes the private keys for the application accounts but it would be an optional to request upon app keys initial setup. + +We indeed think that writing applications that don't need to manipulate the user private keys is a better pattern. For instance, if one needs the user to sign data while being offline, one should for instance rather implement a delegation method to an external application's controlled account rather than storing the user private key on a server that stays online. + +### Persona isolation across applications for privacy + +The persona path is set by the user-wallet interaction and known only by them. There is thus a strict isolation between 2 different persona subpaths as if they were generated by different mnemonics. + + +Instead of personas, an alternative proposal would be to make the `application UID based path` a subset of a user's ethereum main accounts) + +Most wallets use the following derivation path for ethereum accounts: +`m/44'/60'/a'/0/n` +where a is a set of account number and n is the account index + +We could use: +`m/44'/60'/a'/0/n / [Application UID based path] / [App controlled HD subPath]` + +This way, we could use accounts as personas. + +However it does not necessarily make sense to anchor an application to a single main account. Some applications may like to interact with several "main accounts" or allow the user to change the main account they are using to deposit while keeping the same signing `app keys` accounts. Some applications may even like to use non ethereum accounts. + +Also this alternative specification HD path would not be BIP44 compliant but would be using this purpose field. + +Also it may add complexity to restore a wallet and the used accounts, one should remember which account is associated with which application and application can not suggest you which account to use because they are not aware of this part of the path. +If we don't harden the level indexes after the main account index, we could however enumerate all app keys of an user given a list a applications. We would first enumerate over the main accounts (assuming the wallet uses an [account gap limit](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#Address_gap_limit)), then over the Applications list and then over the `Application controlled HD subPath` if it allows to do so and has an account gap limit. + +For the persona specification this may not be possible, unless we impose some structure on the personas such as using a basic index. + +### Hardened and non-hardened indexes: privacy and functionality + +Hardening allows to increase privacy. If the extended public key of a parent level in the HD tree is known, public keys of its children can not be computed if they are hardened. On the contrary if the child indexes are not hardened one can enumerate the child public keys and use that for the application design or to easily restore a wallet and it increases functionality. + +For the first parts of the HD tree, we need isolation and privacy. Thus we use hardened indexes for the persona and application paths in case some extended public key leaks at some previous level of the tree, it would protect the sub trees (of course this has no impact if private keys leak). + +For instance if we don't harden the application path, in case a persona public key is known and the application subpath does not use hardening either, one could get all `app keys` public keys for every application for this persona. + +However the app can use non hardened indexes in their custom path part to be able to benefit from guessing child public keys from parent one (for instance for counterfactual state channel interaction across 2 peers that would like to use new keys every time they counterfactually instantiate a new sub app). + +### Alternatives for the HD derivation path + +Our proposed specification follows [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki): + +`m / purpose' / *` + +It is of course not be BIP44 compliant which uses the following tree level structure: +`m / purpose' / coin_type' / account' / change / address_index` + +One could think of alternative specifications deviating from BIP43 or even BIP32. Or on the contrary, one could try to become BIP44 compliant, although we do not really see the benefit of that for app keys and it would impose serious limitations on how to identify the applications using potentially the `coin_type` field. + + +### HD derivation path purpose field + +If we agree on not using BIP44 but following BIP32 and BIP43, we need to settle on a purpose field. We can either use the 3 depth path proposed here (https://github.com/bitcoin/bips/pull/523) or try to rech agreement on a one depth path. A one depth path should however avoid collision. This can be achieves by either submitting a BIP or by maintening a list of BIP 43 purpose fields. + +We did not find a list of BIP43 purpose code so here is what we could gather: + + +| code | Reference | Title | +|------|--------------------------------------------------------------------------|-------| +| 44 | [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) | Multi-Account Hierarchy for Deterministic Wallets | +| 45 | [BIP45](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki) | Structure for Deterministic P2SH Multisignature Wallets| +| 48 | [SLIP48](https://github.com/satoshilabs/slips/issues/49) | Deterministic Key Hierarchy for Graphene-based Networks | +| 49 | [BIP49](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki) | Derivation scheme for P2WPKH-nested-in-P2SH based accounts | +| 80 | [BIP80](https://github.com/bitcoin/bips/blob/master/bip-0080.mediawiki) | Hierarchy for Non-Colored Voting Pool Deterministic Multisig Wallets | +| 84 | [BIP84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) | Derivation scheme for P2WPKH based accounts | +| 535348 | [Ledger app ssh](https://github.com/LedgerHQ/ledger-app-ssh-agent/blob/master/getPublicKey.py#L49) | | +| 80475047| [GPG/SSH Ledger](https://github.com/LedgerHQ/ledger-app-openpgp-card/blob/master/doc/developper/gpgcard3.0-addon.rst#deterministic-key-derivation)| | +| 1775 | EIP1775 | App Keys: application specific wallet accounts | + + +### Application's identification + +#### Favoring a deterministic scheme for application uids + +Quoting Vitalik in his post [Meta: we should value privacy more](https://ethereum-magicians.org/t/meta-we-should-value-privacy-more/2475), we indeed favor a deterministic scheme for applications specific accounts generation: + +``` +It would be nice to keep wallet software stateless, so users can easily export and import their keys between wallets; this implies using some deterministic scheme like privkey_for_dapp = hash(master_key + dapp_id). But then what is the dapp_id? How would that work for multi-contract dapps? +``` +And we proposed to use the ENS domain hash, or node, as the dapp_id and to use a BIP32 structure instead to derive the private keys. + +#### Alternative: using a centraly maintened index of application uids + +[EIP1581: Non-wallet usage of keys derived from BIP32 trees](https://eips.ethereum.org/EIPS/eip-1581) +also discussed [here](https://ethereum-magicians.org/t/non-wallet-usage-of-keys-derived-from-bip-32-trees/1817/4) proposes a scheme that relies on a list of indexes where application should register (similar to SLIP44 list for instance). + +We think our approach while also being more englobing benefits from not requiring a centrally maintained registry. In our approach every application has already a potential unique identifier assigned to it. + + +#### Shortening the Hash node + +Our current approach uses identification through an ENS name converted to a hash node and sliced fully but one could potentially keep only the first 16 bytes of the node for instance and slice them similarly. This may increase the chance of app collision but we probably can reduce the length while retaining an injective mapping from strings to hashes. + +#### Alternative application identification specification + +For the application unique identifiers, an alternative specification could favor using an `ethereum author address` and including a signed message challenge for author for authentication. + +It would also need to specify how to decompose this address. +The same reasoning as before would apply, if we use an `eth address` of 20 bytes, 160 bits + +e.g. 0x9df77328a2515c6d529bae90edf3d501eaaa268e + +``` +x = x0 || x1 || x2 || x3 || x4 || x5 +``` +where `x0` to `x4` are 30 bits and `x5` is 10 bits. + + +or alternatively equal length +``` +x = x0 || x1 || x2 || x3 || x4 || x5 || x6 || x7 +``` +where `x0` to `x7` are 20 bits. + + +Another alternative could be to use the plain website url and get rid of ens altogether but it would require another way to authenticate applications. See for instance [SLIP13](https://github.com/satoshilabs/slips/blob/master/slip-0013.md) for such a proposal. + +### Application's authentication + +For authentication we use DNS and ENS resolution, and browsing to a given url resolved. A few comments on this: + +A few comments in case of ENS resolution: +* First connection requires the wallet to connect to ethereum mainnet, but once first resolution is done we could use some metadata parameter such as `author address` for a blockchain less authentication of the application (e.g. application server signs a challenge message with the author address resolved in the ENS metadata). + +* The url the name resolves to through ENS can change without the user knowing and then a different application/website may be granted access to his app keys. But this means the ENS name owner address was copromised. This would be similar to using a signing challenge authentified by a known public key. If this known public key is compromised we have a similar problem. + +* Homoglyph attacks are not a bigger problem for `app keys` than it is for ENS since it will not grant access to `app keys` from the real domain (they would be derived along a different path). However homoglyph applications may lure the user to send funds from her main account to an `app key` of a malicious homoglyphic domain. + +Other metadata resolution through ENS that can be used alongside: +* `author address`: already mentioned above +* `contract address`: For app keys that would be designed to interact with a given ethereum contract (for instance app keys for a given token, if one desires to do so), other metadata fields could be used such as contract addresses. +* [TBD] + +In relation to the SLIP13 proposal mentioned above, one could think of alternative specifications that would use some certificate for authentication similar to https. + +### An Account gap limit standard for application controlled hd sub-path? + +If applications don't enumerate through their hd sub-path structure, we won't be able to restore `app keys` accounts by enumeration. However it has benefits to give total freedom to applications over the way they create accounts and use their sub-path. Also, it may be safe to assume that the part of the restoring procedure will be carried by the application itself and not by the wallets. The application will need a way to remember what accounts were derived for each user. + + +### 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 + +From a wallet point of view, there does not seem to be incompatibities 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 ethereum addresses may want to reflect on if and how they would like to leverage the power offered by `app keys` to migrate to them and increase their user's privacy, security and potentially also user-flow. + + + +## Test Cases + +[TBD] + +Provide some examples of accounts derived from a given mnemonic, persona, application and application's custom subpath. + +## Implementation + +[WIP] +[See here for an early implementation of the HD methods](https://github.com/Bunjin/appKeys) + +## 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) + +* [BIP43: Purpose Field for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) + +* [BIP44: Multi-Account Hierarchy for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#Address_gap_limit) + +* [SLIP44: Registered coin types for BIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) + +* [Is there a comprehensive list of registered BIP43 purposes?](https://bitcoin.stackexchange.com/questions/60470/is-there-a-comprehensive-list-of-registered-bip43-purposes) + +#### 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) + +#### Accounts Privacy + + +### ENS +* [EIP137: Ethereum Domain Name Service - specification](https://eips.ethereum.org/EIPS/eip-137) + +* [EIP165: Standard Interface Detection](https://eips.ethereum.org/EIPS/eip-165) + +* [EIP634: Storage of text record in ENS](https://eips.ethereum.org/EIPS/eip-634) + +* [ENS docs about namehash:](http://docs.ens.domains/en/latest/implementers.html#namehash) + +### 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/). diff --git a/EIPS/eip-1803.md b/EIPS/eip-1803.md new file mode 100644 index 0000000000000..448ccbcc62d87 --- /dev/null +++ b/EIPS/eip-1803.md @@ -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/). diff --git a/EIPS/eip-181.md b/EIPS/eip-181.md index 3f0107df30c65..cd8dd71334303 100644 --- a/EIPS/eip-181.md +++ b/EIPS/eip-181.md @@ -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/). diff --git a/EIPS/eip-1820.md b/EIPS/eip-1820.md index 055bae9c1d3f3..c40a5d8a7c133 100644 --- a/EIPS/eip-1820.md +++ b/EIPS/eip-1820.md @@ -2,7 +2,7 @@ eip: 1820 title: Pseudo-introspection Registry Contract author: Jordi Baylina , Jacques Dafflon -discussions-to: https://github.com/ethereum/EIPs/pulls/1820 +discussions-to: https://github.com/ethereum/EIPs/pull/1820 status: Final type: Standards Track category: ERC diff --git a/EIPS/eip-1829.md b/EIPS/eip-1829.md index c19892e6d551d..0a075ea3cc9b2 100644 --- a/EIPS/eip-1829.md +++ b/EIPS/eip-1829.md @@ -14,7 +14,7 @@ created: 2019-03-06 ## Simple Summary -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-knownledge proofs. +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. @@ -59,7 +59,7 @@ The total gas cost is `BASE_GAS` plus `ADD_GAS` for each `s_i` that is `1` and ` ### Encoding of points -Encode as `(x, y')` where `s` is the indicates the wheter `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. +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)` | |--------|-----| @@ -110,14 +110,14 @@ TODO: The special cases for `α` and `β` might be worth implementing and offere **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 addtion, 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 benfit from this. +**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 pratically demonstrated by [Weierstrudel][ws]. +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 mittigations for side-channel attacks are necessary. +**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. diff --git a/EIPS/eip-1884.md b/EIPS/eip-1884.md index 1a1f64dae9a9e..57735c444e35f 100644 --- a/EIPS/eip-1884.md +++ b/EIPS/eip-1884.md @@ -7,6 +7,7 @@ category: Core discussions-to: https://ethereum-magicians.org/t/opcode-repricing/3024 status: Draft created: 2019-03-28 +requires: 150, 1052 --- @@ -33,9 +34,10 @@ If operations are well-balanced, we can maximise the block gaslimit and have a m At block `N`, -- The `SLOAD` operation changes from `200` to `800` gas, -- The `BALANCE` operation changes from `400` to `700` gas, -- A new opcode, `SELFBALANCE` is introduced at `0x46`. +- 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. @@ -47,7 +49,7 @@ Here are two charts, taken from a full sync using Geth. The execution time was m ![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` opcode has position one which I believe can be optimized away within the client -- which is not the case with `SLOAD`/`BALANCE`. +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. @@ -90,6 +92,15 @@ opcodes: `EXTBALANCE(address)` and `SELFBALANCE`, and have two different prices. * 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: diff --git a/EIPS/eip-1895.md b/EIPS/eip-1895.md new file mode 100644 index 0000000000000..5c097b75c4115 --- /dev/null +++ b/EIPS/eip-1895.md @@ -0,0 +1,164 @@ +--- +eip: 1895 +title: Support for an Elliptic Curve Cycle +author: Alexandre Belling +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 / <>` + +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 = <> +MNT_X_MUL = <> +MNT_X_PAIRING = <> +``` + +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 + + + +## 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 + + + +* [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/). diff --git a/EIPS/eip-1898.md b/EIPS/eip-1898.md index 7ea8da1acb231..677c7e85a6269 100644 --- a/EIPS/eip-1898.md +++ b/EIPS/eip-1898.md @@ -6,7 +6,7 @@ type: Standards Track category: Interface status: Draft created: 2019-04-01 -requires: 234 +requires: 234, 1474 --- ## Simple Summary @@ -38,11 +38,17 @@ Since there is no way to clearly distinguish between a DATA parameter and a QUAN - `blockNumber`: QUANTITY - a block number - `blockHash`: DATA - a block hash -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: +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 @@ -61,6 +67,17 @@ Backwards compatible. ## Test Cases +- `eth_getStorageAt [ "0x
", { "blockNumber": "0x0" }` -> return storage at given address in genesis block +- `eth_getStorageAt [ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }` -> return storage at given address in genesis block +- `eth_getStorageAt [ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false }` -> return storage at given address in genesis block +- `eth_getStorageAt [ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }` -> return storage at given address in genesis block +- `eth_getStorageAt [ "0x
", { "blockHash": "0x" }` -> raise block-not-found error +- `eth_getStorageAt [ "0x
", { "blockHash": "0x", "requireCanonical": false }` -> raise block-not-found error +- `eth_getStorageAt [ "0x
", { "blockHash": "0x", "requireCanonical": true }` -> raise block-not-found error +- `eth_getStorageAt [ "0x
", { "blockHash": "0x" }` -> return storage at given address in specified block +- `eth_getStorageAt [ "0x
", { "blockHash": "0x", "requireCanonical": false }` -> return storage at given address in specified block +- `eth_getStorageAt [ "0x
", { "blockHash": "0x", "requireCanonical": true }` -> raise block-not-canonical error + ## Implementation None yet. diff --git a/EIPS/eip-1900.md b/EIPS/eip-1900.md new file mode 100644 index 0000000000000..decd47e06d7c7 --- /dev/null +++ b/EIPS/eip-1900.md @@ -0,0 +1,276 @@ +--- +eip: 1900 +title: dType - Decentralized Type System for EVM +author: Loredana Cirstea (@loredanacirstea), Christian Tzurcanu (@ctzurcanu) +discussions-to: https://github.com/ethereum/EIPs/issues/1882 +status: Draft +type: Standards Track +category: ERC +created: 2019-03-28 +--- + +## Simple Summary + +The EVM and related languages such as Solidity need consensus on an extensible Type System in order to further evolve into the Singleton Operating System (The World Computer). + +## Abstract + +We are proposing a decentralized Type System for Ethereum, to introduce data definition (and therefore ABI) consistency. This ERC focuses on defining an on-chain Type Registry (named `dType`) and a common interface for creating types, based on `struct`s. + + +## Motivation + +In order to build a network of interoperable protocols on Ethereum, we need data standardization, to ensure a smooth flow of on-chain information. Off-chain, the Type Registry will allow a better analysis of blockchain data (e.g. for blockchain explorers) and creation of smart contract development tools for easily using existing types in a new smart contract. + +However, this is only the first phase. As defined in this document and in the future proposals that will be based on this one, we are proposing something more: a decentralized Type System with Data Storage - [ERC-2158](https://github.com/ethereum/EIPs/pull/2158). In addition, developers can create libraries of `pure` functions that know how to interact and modify the data entries - [dType Functions Extension](https://github.com/ethereum/EIPs/issues/1921). This will effectively create the base for a general functional programming system on Ethereum, where developers can use previously created building blocks. + +To summarize: + +* We would like to have a good decentralized medium for integrating all Ethereum data, and relationships between the different types of data. Also, a way to address the behavior related to each data type. +* Functional programming becomes easier. Functions like `map`, `reduce`, `filter`, are implemented by each type library. +* Solidity development tools could be transparently extended to include the created types (For example in IDEs like Remix). At a later point, the EVM itself can have precompiled support for these types. +* The system can be easily extended to types pertaining to other languages. (With type definitions in the source (Swarm stored source code in the respective language)) +* The dType database should be part of the System Registry for the Operating System of The World Computer + + +## Specification + +The Type Registry can have a governance protocol for its CRUD operations. However, this, and other permission guards are not covered in this proposal. + +### Type Definition and Metadata + +The dType registry should support the registration of Solidity's elementary and complex types. In addition, it should also support contract events definitions. In this EIP, the focus will be on describing the minimal on-chain type definition and metadata needed for registering Solidity user-defined types. + +#### Type Definition: TypeLibrary + +A type definition consists of a type library containing: +- the nominal `struct` used to define the type +- additional functions: + - `isInstanceOf`: checks whether a given variable is an instance of the defined type. Additional rules can be defined for each type fields, e.g. having a specific range for a `uint16 amount`. + - provide HOFs such as `map`, `filter`, `reduce` + - `structureBytes` and `destructureBytes`: provide type structuring and destructuring. This can be useful for low-level calls or assembly code, when importing contract interfaces is not an efficient option. It can also be used for type checking. + +A simple example is: + +```solidity +pragma solidity ^0.5.0; +pragma experimental ABIEncoderV2; + +library myBalanceLib { + + struct myBalance { + string accountName; + uint256 amount; + } + + function structureBytes(bytes memory data) pure public returns(myBalance memory balance) + + function destructureBytes(myBalance memory balance) pure public returns(bytes memory data) + + function isInstanceOf(myBalance memory balance) pure public returns(bool isInstance) + + function map( + address callbackAddr, + bytes4 callbackSig, + myBalance[] memory balanceArr + ) + view + internal + returns (myBalance[] memory result) +} +``` + +Types can also use existing types in their composition. However, this will always result in a directed acyclic graph. + +```solidity +library myTokenLib { + using myBalanceLib for myBalanceLib.myBalance; + + struct myToken { + address token; + myBalanceLib.myBalance; + } +} +``` + +#### Type Metadata: dType Registry + +Type metadata will be registered on-chain, in the dType registry contract. This consists of: +- `name` - the type's name, as it would be used in Solidity; it can be stored as a `string` or encoded as `bytes`. The name can have a human-readable part and a version number. +- `typeChoice` - used for storing additional ABI data that differentiate how types are handled on and off chain. It is defined as an `enum` with the following options: `BaseType`, `PayableFunction`, `StateFunction`, `ViewFunction`, `PureFunction`, `Event` +- `contractAddress` - the Ethereum `address` of the `TypeRootContract`. For this proposal, we can consider the Type Library address as the `TypeRootContract`. Future EIPs will make it more flexible and propose additional TypeStorage contracts that will modify the scope of `contractAddress` - [ERC-2158](https://github.com/ethereum/EIPs/pull/2158). +- `source` - a `bytes32` Swarm hash where the source code of the type library and contracts can be found; in future EIPs, where dType will be extended to support other languages (e.g. JavaScript, Rust), the file identified by the Swarm hash will contain the type definitions in that language. +- `types` - metadata for subtypes: the first depth level internal components. This is an array of objects (`structs`), with the following fields: + - `name` - the subtype name, of type `string`, similar to the above `name` definition + - `label` - the subtype label + - `dimensions` - `string[]` used for storing array dimensions. E.g.: + - `[]` -> `TypeA` + - `[""]` -> `TypeA[]` + - `["2"]` -> `TypeA[2]` + - `["",""]` -> `TypeA[][]` + - `["2","3"]` -> `TypeA[2][3]` + +Examples of metadata, for simple, value types: +```javascript +{ + "contractAddress": "0x0000000000000000000000000000000000000000", + "typeChoice": 0, + "source": "0x0000000000000000000000000000000000000000000000000000000000000000", + "name": "uint256", + "types": [] +} + +{ + "contractAddress": "0x0000000000000000000000000000000000000000", + "typeChoice": 0, + "source": "0x0000000000000000000000000000000000000000000000000000000000000000", + "name": "string", + "types": [] +} +``` + +Composed types can be defined as: +```javascript +{ + "contractAddress": "0x105631C6CdDBa84D12Fa916f0045B1F97eC9C268", + "typeChoice": 0, + "source": , + "name": "myBalance", + "types": [ + {"name": "string", "label": "accountName", dimensions: []}, + {"name": "uint256", "label": "amount", dimensions: []} + ] +} +``` + +Composed types can be further composed: +```javascript +{ + "contractAddress": "0x91E3737f15e9b182EdD44D45d943cF248b3a3BF9", + "typeChoice": 0, + "source": , + "name": "myToken", + "types": [ + {"name": "address", "label": "token", dimensions: []}, + {"name": "myBalance", "label": "balance", dimensions: []} + ] +} +``` + +`myToken` type will have the final data format: `(address,(string,uint256))` and a labeled format: `(address token, (string accountName, uint256 amount))`. + +##### dType Registry Data Structures and Interface + +To store this metadata, the dType registry will have the following data structures: + +```solidity +enum TypeChoices { + BaseType, + PayableFunction, + StateFunction, + ViewFunction, + PureFunction, + Event +} + +struct dTypes { + string name; + string label; + string[] dimensions; +} + +struct dType { + TypeChoices typeChoice; + address contractAddress; + bytes32 source; + string name; + dTypes[] types; +} + +``` + +For storage, we propose a pattern which isolates the type metadata from additional storage-specific data and allows CRUD operations on records. + +```solidity +// key: identifier +mapping(bytes32 => Type) public typeStruct; + +// array of identifiers +bytes32[] public typeIndex; + +struct Type { + dType data; + uint256 index; +} +``` + +Note that we are proposing to define the type's primary identifier, `identifier`, as `keccak256(abi.encodePacked(name))`. If the system is extended to other programming languages, we can define `identifier` as `keccak256(abi.encodePacked(language, name))`. +Initially, single word English names can be disallowed, avoiding name squatting. + + +The dType registry interface is: + +```solidity +import './dTypeLib.sol'; +interface dType { + event LogNew(bytes32 indexed identifier, uint256 indexed index); + event LogUpdate(bytes32 indexed identifier, uint256 indexed index); + event LogRemove(bytes32 indexed identifier, uint256 indexed index); + + function insert(dTypeLib.dType calldata data) external returns (bytes32 identifier); + + function remove(bytes32 identifier) external returns(uint256 index); + + function count() external view returns(uint256 counter); + + function getTypeIdentifier(string memory name) pure external returns (bytes32 identifier); + + function getByIdentifier(bytes32 identifier) view external returns(dTypeLib.dType memory dtype); + + function get(string memory name) view external returns(dTypeLib.dType memory dtype); + + function isRegistered(bytes32 identifier) view external returns(bool registered); +} +``` + +**Notes:** + +To ensure backward compatibility, we suggest that updating types should not be supported. + +The `remove` function can also be removed from the interface, to ensure immutability. One reason for keeping it would be clearing up storage for types that are not in use or have been made obsolete. However, this can have undesired effects and should be accompanied by a solid permissions system, testing and governance process. This part will be updated when enough feedback has been received. + +## Rationale + +The Type Registry must store the minimum amount of information for rebuilding the type ABI definition. This allows us to: +* support on-chain interoperability +* decode blockchain side effects off-chain (useful for block explorers) +* allow off-chain tools to cache and search through the collection (e.g. editor plugin for writing typed smart contracts) + +There is one advantage that has become clear with the emergence of global operating systems, like Ethereum: we can have a global type system through which the system’s parts can interoperate. Projects should agree on standardizing types and a type registry, continuously working on improving them, instead of creating encapsulated projects, each with their own types. + +The effort of having consensus on new types being added or removing unused ones is left to the governance system. + +After the basis of such a system is specified, we can move forward to building a static type checking system at compile time, based on the type definitions and rules stored in the dType registry. + +The Type Library must express the behavior strictly pertinent to its defined type. Additional behavior, required by various project's business logic can be added later, through libraries containing functions that handle the respective type. These can also be registered in dType, but will be detailed in a future ERC. + +This is an approach that will separate definitions from stored data and behavior, allowing for easier and more secure fine-grained upgrades. + +## Backwards Compatibility + +This proposal does not affect extant Ethereum standards or implementations. It uses the present experimental version of ABIEncoderV2. + +## Test Cases + +Will be added. + +## Implementation + +An in-work implementation can be found at https://github.com/pipeos-one/dType/tree/master/contracts/contracts. +This proposal will be updated with an appropriate implementation when consensus is reached on the specifications. + +A video demo of the current implementation (a more extended version of this proposal) can be seen at https://youtu.be/pcqi4yWBDuQ. + + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1901.md b/EIPS/eip-1901.md new file mode 100644 index 0000000000000..68b99df64b3cb --- /dev/null +++ b/EIPS/eip-1901.md @@ -0,0 +1,80 @@ +--- +eip: 1901 +title: Add OpenRPC Service Discovery To JSON-RPC Services +author: Shane Jonas (@shanejonas), Zachary Belford (@belfordz) +discussions-to: https://github.com/ethereum/EIPs/issues/1902 +status: Draft +type: Standards Track +category: Interface +created: 2019-02-25 +--- + +## Abstract +### What is this? + +This is a proposal to add [OpenRPC](https://github.com/open-rpc/spec) support to existing and future JSON-RPC services by adding the method [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) to the projects [JSON-RPC](https://www.jsonrpc.org/specification) APIs, enabling automation and tooling. + +The OpenRPC Document and generated Documentation that specifies all the methods an EVM-based blockchain should implement can be found [here](https://github.com/etclabscore/ethereum-json-rpc-specification). + +This was first proposed [here as an ECIP](https://github.com/etclabscore/ECIPs/blob/master/ECIPs/ECIP-1053.md), but the benefits of this kind of tooling is apparent across Bitcoin, Ethereum Classic, Ethereum and other JSON-RPC accessible blockchains. + +## Motivation + +Although [EIP-1474](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1474.md) outlines a JSON-RPC specification. Ethereum still lacks a machine-readable JSON-RPC Specification that can be used as the industry standard for tooling. This proposal attempts to standardize such a specification in a way that is versionable, and both human and machine readable. + +Ethereum clients can expose RPC endpoints with different method signatures and cause compatibility issues between clients. + +Developers need a reliable developer experience, and an industry standard way to describe Ethereum JSON-RPC 2.0 APIs. + +## Specification + +### What is OpenRPC? + +The [OpenRPC](https://github.com/open-rpc/spec) Specification defines a standard, programming language-agnostic interface description for [JSON-RPC 2.0](https://www.jsonrpc.org/specification) APIs, which allows both humans and computers to discover and understand the capabilities of a service without requiring access to source code, additional documentation, or inspection of network traffic. When properly defined via OpenRPC, a consumer can understand and interact with the remote service with a minimal amount of implementation logic, and share these logic patterns across use cases. Similar to what interface descriptions have done for lower-level programming, the OpenRPC Specification removes guesswork in calling a service. + +##### Structure + +This is the structure of an OpenRPC Document: + +![openrpc-spec-structure](../assets/eip-1901/OpenRPC_structure.png) + +JSON-RPC APIs can support the OpenRPC specification by implementing a service discovery method that will return the [OpenRPC document](https://github.com/open-rpc/spec#openrpc-document) for the JSON-RPC API. The method MUST be named `rpc.discover`. The `rpc.` prefix is a reserved method prefix for [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification) system extensions. + +### Use Case + +This is the vision for the use case of OpenRPC and how it would relate to a client implementation like multi-geth: + +![MultGethRpc-usecase](../assets/eip-1901/multi-geth-use-case.png) + +## Rationale + +### Why would we do this? +Services need to figure out how to talk to each other. If we really want to build the next generation of automation, then having up to date libraries, documented APIs, and modern tools are going to provide easy discovery, on-boarding, and enable end user and developer interaction. + +Use cases for machine-readable [JSON-RPC 2.0](https://www.jsonrpc.org/specification) API definition documents include, but are not limited to: + +- A common vocabulary and document will keep developers, testers, architects, and technical writers all in sync. +- Server stubs/skeletons generated in many languages +- Clients generated in many languages +- Mock Server generated in many languages +- Tests generated in many languages +- Documentation Generation + +### Alternative + +[OpenRPC](https://github.com/open-rpc/spec) documents just describe [JSON-RPC](https://www.jsonrpc.org/specification) APIs services, and are represented in JSON format. These documents may be produced and served statically OR generated dynamically from an application and returned via the [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) method. This gives projects and communities the opportunity to adopt tools, documentation, and clients outlined in the [etclabscore/ethereum-json-rpc-specification](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1474.md) before the [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) method is implemented for a particular client. + +## Implementation + +- [Multi-Geth OpenRPC Discovery](https://github.com/multi-geth/multi-geth#openrpc-discovery) + +## Resources + +- [Multi-Geth OpenRPC Discovery](https://github.com/multi-geth/multi-geth#openrpc-discovery) +- [EDCON 2019 talk on OpenRPC and The Future of JSON-RPC Tooling](https://www.youtube.com/watch?v=UgSPMZ9FQ4Q) +- [etclabscore/ethereum-json-rpc-specification](https://github.com/etclabscore/ethereum-json-rpc-specification) +- [open-rpc.org](https://open-rpc.org) + +## Copyright + + Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/EIPS/eip-1922.md b/EIPS/eip-1922.md index 9742dd364f939..e0f9d76ae6150 100644 --- a/EIPS/eip-1922.md +++ b/EIPS/eip-1922.md @@ -89,7 +89,7 @@ interface ERC165 { ⚠️ TODO: Add a specific reference to libsnark here, explaining the choice of variable names. -:warning: TODO: Explain how _C_ may not necessarilly be a satisfiable arithmetic circuit of logical statements. As current, this is a limitation to certain kinds of SNARKS. Whereas the source references also mention polynomials, and other applications. +:warning: TODO: Explain how _C_ may not necessarily be a satisfiable arithmetic circuit of logical statements. As current, this is a limitation to certain kinds of SNARKS. Whereas the source references also mention polynomials, and other applications. _C_ — A satisfiable arithmetic circuit abstraction of logical statements. diff --git a/EIPS/eip-1930.md b/EIPS/eip-1930.md new file mode 100644 index 0000000000000..abf1456cb9b15 --- /dev/null +++ b/EIPS/eip-1930.md @@ -0,0 +1,120 @@ +--- +eip: 1930 +title: CALLs with strict gas semantic. Revert if not enough gas available. +author: Ronan Sandford (@wighawag) +type: Standards Track +discussions-to: https://github.com/ethereum/EIPs/issues/1930 +category: Core +status: Draft +created: 2019-04-10 +--- + +## Simple Summary + +Add the ability for smart contract to execute calls with a specific amount of gas. If this is not possible the execution should revert. + +## Abstract + +The current CALL, DELEGATE_CALL, STATIC_CALL opcode do not enforce the gas being sent, they simply consider the gas value as a maximum. This pose serious problem for applications that require the call to be executed with a precise amount of gas. + +This is for example the case for meta-transaction where the contract needs to ensure the call is executed exactly as the signing user intended. + +But this is also the case for common use cases, like checking "on-chain" if a smart contract support a specific interface (via [EIP-165](http://eips.ethereum.org/EIPS/eip-165) for example). + +The solution presented here is to add new opcodes that enforce the amount of gas specified : the call either proceed with the exact amount of gas or do not get executed and the current call revert. + + +### Specification + +- add a new variant of the CALL opcode where the gas specified is enforced so that if the gas left at the point of call is not enough to give the specified gas to the destination, the current call revert +- add a new variant of the DELEGATE_CALL opcode where the gas specified is enforced so that if the gas left at the point of call is not enough to give the specified gas to the destination, the current call revert +- add a new variant of the STATIC_CALL opcode where the gas specified is enforced so that if the gas left at the point of call is not enough to give the specified gas to the destination, the current call revert + +In other words, based on [EIP-150](http://eips.ethereum.org/EIPS/eip-150), the current call must revert unless G >= I x 64/63 where G is gas left at the point of call (after deducing the cost of the call itself) and I is the gas specified. + +So instead of +``` +availableGas = availableGas - base +gas := availableGas - availableGas/64 +... +if !callCost.IsUint64() || gas < callCost.Uint64() { + return gas, nil +} +``` +see https://github.com/ethereum/go-ethereum/blob/7504dbd6eb3f62371f86b06b03ffd665690951f2/core/vm/gas.go#L41-L48 + +we would have +``` +availableGas = availableGas - base +gas := availableGas - availableGas/64 +if !callCost.IsUint64() || gas < callCost.Uint64() { + return 0, errNotEnoughGas +} +``` + +### Rationale + +Currently the gas specified as part of these opcodes is simply a maximum value. And due to the behavior of [EIP-150](http://eips.ethereum.org/EIPS/eip-150) it is possible for an external call to be given less gas than intended (less than the gas specified as part of the CALL) while the rest of the current call is given enough to continue and succeed. Indeed since with EIP-150, the external call is given at max ```G - Math.floor(G/64)``` where G is the gasleft() at the point of the CALL, the rest of the current call is given ```Math.floor(G/64)``` which can be plenty enough for the transaction to succeed. For example, when G = 6,400,000 the rest of the transaction will be given 100,000 gas plenty enough in many case to succeed. + +This is an issue for contracts that require external call to only fails if they would fails with enough gas. This requirement is present in smart contract wallet and meta transaction in general, where the one executing the transaction is not the signer of the execution data. Because in such case, the contract needs to ensure the call is executed exactly as the signing user intended. + +But this is also true for simple use case, like checking if a contract implement an interface via EIP-165. Indeed as specified by such EIP, the ```supporstInterface``` method is bounded to use 30,000 gas so that it is theorically possible to ensure that the throw is not a result of a lack of gas. Unfortunately due to how the different CALL opcodes behave contracts can't simply rely on the gas value specified. They have to ensure by other means that there is enough gas for the call. + +Indeed, if the caller do not ensure that 30,000 gas or more is provided to the callee, the callee might throw because of a lack of gas (and not because it does not support the interface), and the parent call will be given up to 476 gas to continue. This would result in the caller interepreting wrongly that the callee is not implementing the interface in question. + +While such requirement can be enforced by checking the gas left according to EIP-150 and the precise gas required before the call (see solution presented in that [bug report](https://web.solidified.io/contract/5b4769b1e6c0d80014f3ea4e/bug/5c83d86ac2dd6600116381f9) or after the call (see the native meta transaction implementation [here](https://github.com/pixowl/thesandbox-contracts/blob/623f4d4ca10644dcee145bcbd9296579a1543d3d/src/Sand/erc20/ERC20MetaTxExtension.sol#L176), it would be much better if the EVM allowed us to strictly specify how much gas is to be given to the CALL so contract implementations do not need to follow [EIP-150](http://eips.ethereum.org/EIPS/eip-150) behavior and the current gas pricing so closely. + +This would also allow the behaviour of [EIP-150](http://eips.ethereum.org/EIPS/eip-150) to be changed without having to affect contract that require this strict gas behaviour. + +As mentioned, such strict gas behaviour is important for smart contract wallet and meta transaction in general. +The issue is actually already a problem in the wild as can be seen in the case of Gnosis safe which did not consider the behavior of EIP-150 and thus fails to check the gas properly, requiring the safe owners to add otherwise unnecessary extra gas to their signed message to avoid the possibility of losing funds. See https://github.com/gnosis/safe-contracts/issues/100 + +As for EIP-165, the issue already exists in the example implementation presented in the EIP. Please see the details of the issue [here](https://github.com/ethereum/EIPs/pull/881#issuecomment-491677748) + +The same issue exists also on OpenZeppelin implementation, a library used by many. It does not for perform any check on gas before calling ```supportsInterface``` with 30,000 gas (see [here](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/fa004a7f5de572b3dbcde1a8a81f9a87e353e799/contracts/introspection/ERC165Checker.sol#L37) and is thus vulnerable to the issue mentioned. + + +While such issue can be prevented today by checking the gas with EIP-150 in mind, a solution at the opcode level is more elegant. + +Indeed, the two possible ways to currently enforce that the correct amount of gas is sent are as follow : + +1) check done before the call + +``` +uint256 gasAvailable = gasleft() - E; +require(gasAvailable - gasAvailable / 64 >= `txGas`, "not enough gas provided") +to.call.gas(txGas)(data); // CALL +``` +where E is the gas required for the operation between the call to ```gasleft()``` and the actual call PLUS the gas cost of the call itself. +While it is possible to simply over estimate ```E``` to prevent call to be executed if not enough gas is provided to the current call it would be better to have the EVM do the precise work itself. As gas pricing continue to evolve, this is important to have a mechanism to ensure a specific amount of gas is passed to the call so such mechanism can be used without having to relies on a specific gas pricing. + + +2) check done after the call: + +``` +to.call.gas(txGas)(data); // CALL +require(gasleft() > txGas / 63, "not enough gas left"); +``` +This solution does not require to compute a ```E``` value and thus do not relies on a specific gas pricing (except for the behaviour of EIP-150) since if the call is given not enough gas and fails for that reason, the condition above will always fail, ensuring the current call will revert. +But this check still pass if the gas given was less AND the external call reverted or succeeded EARLY (so that the gas left after the call > txGas / 63). +This can be an issue if the code executed as part of the CALL is reverting as a result of a check against the gas provided. Like a meta transaction in a meta transaction. + +Similarly to the the previous solution, an EVM mechanism would be much better. + +## Backwards Compatibility + +Backwards compatible as it introduce new opcodes. + +## Test Cases + +## Implementation + +None fully implemented yet. But see Specifications for an example in geth. + +## References + +1. EIP-150, http://eips.ethereum.org/EIPS/eip-150 + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1948.md b/EIPS/eip-1948.md new file mode 100644 index 0000000000000..a944d69e164c3 --- /dev/null +++ b/EIPS/eip-1948.md @@ -0,0 +1,159 @@ +--- +eip: 1948 +title: Non-fungible Data Token +author: Johann Barbie (@johannbarbie), Ben Bollen , pinkiebell (@pinkiebell) +discussions-to: https://ethereum-magicians.org/t/erc-non-fungible-data-token/3139 +status: Draft +type: Standards Track +category: ERC +created: 2019-04-18 +requires: 721 +--- + +## Simple Summary + +Some NFT use-cases require to have dynamic data associated with a non-fungible token that can change during its lifetime. Examples for dynamic data: +- cryptokitties that can change color +- intellectual property tokens that encode rights holders +- tokens that store data to transport them across chains + +The existing metadata standard does not suffice as data can only be set at minting time and not modified later. + +## Abstract + +Non-fungible tokens (NFTs) are extended with the ability to store dynamic data. A 32 bytes data field is added and a read function allows to access it. The write function allows to update it, if the caller is the owner of the token. An event is emitted every time the data updates and the previous and new value is emitted in it. + +## Motivation + +The proposal is made to standardize on tokens with dynamic data. Interactions with bridges for side-chains like xDAI or Plasma chains will profit from the ability to use such tokens. Protocols that build on data tokens like [distributed breeding](https://ethresear.ch/t/a-distributed-breeding-function/5264) will be enabled. + +## Specification + +An extension of [ERC721](https://eips.ethereum.org/EIPS/eip-721) interface with the following functions and events is suggested: + +``` solidity +pragma solidity ^0.5.2; + +/** + * @dev Interface of the ERC1948 contract. + */ +interface IERC1948 { + + /** + * @dev Emitted when `oldData` is replaced with `newData` in storage of `tokenId`. + * + * Note that `oldData` or `newData` may be empty bytes. + */ + event DataUpdated(uint256 indexed tokenId, bytes32 oldData, bytes32 newData); + + /** + * @dev Reads the data of a specified token. Returns the current data in + * storage of `tokenId`. + * + * @param tokenId The token to read the data off. + * + * @return A bytes32 representing the current data stored in the token. + */ + function readData(uint256 tokenId) external view returns (bytes32); + + /** + * @dev Updates the data of a specified token. Writes `newData` into storage + * of `tokenId`. + * + * @param tokenId The token to write data to. + * @param newData The data to be written to the token. + * + * Emits a `DataUpdated` event. + */ + function writeData(uint256 tokenId, bytes32 newData) external; + +} +``` + +## Rationale + +The suggested data field in the NFT is used either for storing data directly, like a counter or address. If more data is required the implementer should fall back to authenticated data structures, like merkle- or patricia-trees. + +The proposal for this ERC stems from the [distributed breeding proposal](https://ethresear.ch/t/a-distributed-breeding-function/5264) to allow better integration of NFTs across side-chains. [ost.com](https://ost.com/), [Skale](https://skalelabs.com/), [POA](https://poa.network/), and [LeapDAO](https://leapdao.org/) have been part of the discussion. + +## Backwards Compatibility + +🤷‍♂️ No related proposals are known to the author, hence no backwards compatibility to consider. + +## Test Cases + +Simple happy test: + +``` javascript +const ERC1948 = artifacts.require('./ERC1948.sol'); + +contract('ERC1948', (accounts) => { + const firstTokenId = 100; + const empty = '0x0000000000000000000000000000000000000000000000000000000000000000'; + const data = '0x0101010101010101010101010101010101010101010101010101010101010101'; + let dataToken; + + beforeEach(async () => { + dataToken = await ERC1948.new(); + await dataToken.mint(accounts[0], firstTokenId); + }); + + it('should allow to write and read', async () => { + let rsp = await dataToken.readData(firstTokenId); + assert.equal(rsp, empty); + await dataToken.writeData(firstTokenId, data); + rsp = await dataToken.readData(firstTokenId); + assert.equal(rsp, data); + }); + +}); +``` + + +## Implementation + +An example implementation of the interface in solidity would look like this: + +``` solidity +/** + * @dev Implementation of ERC721 token and the `IERC1948` interface. + * + * ERC1948 is a non-fungible token (NFT) extended with the ability to store + * dynamic data. The data is a bytes32 field for each tokenId. If 32 bytes + * do not suffice to store the data, an authenticated data structure (hash or + * merkle tree) shall be used. + */ +contract ERC1948 is IERC1948, ERC721 { + + mapping(uint256 => bytes32) data; + + /** + * @dev See `IERC1948.readData`. + * + * Requirements: + * + * - `tokenId` needs to exist. + */ + function readData(uint256 tokenId) external view returns (bytes32) { + require(_exists(tokenId)); + return data[tokenId]; + } + + /** + * @dev See `IERC1948.writeData`. + * + * Requirements: + * + * - `msg.sender` needs to be owner of `tokenId`. + */ + function writeData(uint256 tokenId, bytes32 newData) external { + require(msg.sender == ownerOf(tokenId)); + emit DataUpdated(tokenId, data[tokenId], newData); + data[tokenId] = newData; + } + +} +``` + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1959.md b/EIPS/eip-1959.md new file mode 100644 index 0000000000000..40af70b401ca7 --- /dev/null +++ b/EIPS/eip-1959.md @@ -0,0 +1,79 @@ +--- +eip: 1959 +title: New Opcode to check if a chainID is part of the history of chainIDs +author: Ronan Sandford (@wighawag) +category: Core +type: Standards Track +discussions-to: https://ethereum-magicians.org/t/eip-1959-valid-chainid-opcode/3170 +status: Draft +created: 2019-04-20 +requires: 155 +--- + + +## Simple Summary +To protect off-chain messages from being reused across different chain, a mechanism need to be given to smart contract to only accept messages for that chain. Since a chain can change its chainID, the mechanism should consider old chainID valid. + +## Abstract +This EIP adds an opcode that returns whether the specific number passed in has been a valid chainID (EIP-155 unique identifier) in the history of the chain (including the current chainID). + +## Motivation +[EIP-155](https://eips.ethereum.org/EIPS/eip-155) proposes to use the chain ID to prevent replay attacks between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling signatures, especially for Layer 2 signature schemes using [EIP-712](https://eips.ethereum.org/EIPS/eip-712). + +[EIP-1344](https://eips.ethereum.org/EIPS/eip-1344) is attempting to solve this by giving smart contract access to the tip of the chainID history. This is insufficient as such value is changing. Hence why EIP-1344 describes a contract based solution to work around the problem. It would be better to solve it in a simpler, cheaper and safer manner, removing the potential risk of misuse present in EIP-1344. + +## Specification +Adds a new opcode ```VALID_CHAINID``` at 0x46, which uses 1 stack argument : a 32 bytes value that represent the chainID to test. It will push ```0x1``` onto the stack if the uint256 value is part of the history (since genesis) of chainIDs of that chain, ```0x0``` otherwise. + +The operation costs `G_blockhash` to execute. + +The cost of the operation might need to be adjusted later as the number of chainID in the history of the chain grows. + +Note though that the alternative to keep track of old chainID is to implement a smart contract based caching solution as EIP-1344 proposes comes with an overall higher gas cost. As such the gas cost is simply a necessary cost for the feature. + +## Rationale +The only approach available today is to specify the chain ID at compile time. Using this approach will result in problems after a contentious hardfork as the contract can't accept message signed with a new chainID. + +The approach proposed by EIP-1344 is to give access to the latest chainID. This is in itself not sufficient and pose the opposite of the problem mentioned above since as soon as a hardfork that change the chainID happens, every L2 messages signed as per [EIP-712](https://eips.ethereum.org/EIPS/eip-712) (with the previous chainID) will fails to be accepted by the contracts after the fork. + +That's why in the rationale of EIP-1344 it is mentioned that users need to implement/use a mechanism to verify the validity of past chainID via a trustless cache implemented via smart contract. + +While this works (except for a temporary gap where the immediately previous chainID is not considered valid), this is actually a required procedure for all contracts that want to accept L2 messages since without it, messages signed before an hardfork that updated the chainID would be rejected. In other words, EIP-1344 expose such risk and it is easy for contract to not consider it by simply checking ```chainID == CHAIN_ID()``` without considering past chainIDs. + +Indeed letting contracts access the latest chainID for L2 message verification is dangerous. The latest chainID is only the tip of the chainID history. As a changing value, the latest chainID is thus not appropriate to ensure the validity of L2 messages. + +Users signing off-chain messages expect their messages to be valid from the time of signing and do not expect these message to be affected by a future hardfork. If the contract use the latest chainID as is for verification, the messages would be invalid as soon as a hardfork that update the chainID happens. For some applications, this will require users to resubmit a new message (think meta transaction), causing them potential loss (or some inconvenience during the hardfork transition), but for some other applications (think state channel) the whole off-chain state become inaccessible, resulting in potentially disastrous situations. + +In other words, we should consider all off-chain messages (with valid chainID) as part of the chain's offchain state. The opcode proposed here, offer smart contracts a simple and safe method to ensure that the offchain state stay valid across fork. + +As for replay protection, the idea of considering all of the off-chain messages signed with valid chainID as part of the chain's offchain-state means that all of these off-chain messages can be reused on the different forks which share a common chainID history (up to where they differ). This is actually an important feature since as mentioned, users expect their signed messages to be valid from the time of signing. From that time onwards these messages should be considered as part of the chain's offchain state. A hardfork should not thus render them invalid. This is similar to how the previous on-chain state is shared between 2 hardforks. + +The wallets will make sure that at any time, a signing message request use the latest chainID of the chain being used. This prevent replay attack onto chain that have different chainID histories (they would not have the same latest chainID). + +Now it is argued in the [EIP1344 discussion](https://ethereum-magicians.org/t/eip-1344-add-chain-id-opcode/1131) that when a contentious hardfork happen and one side of the fork decide to not update its chainID, that side of the chain would be vulnerable to replays since users will keep signing with a chainID that is also valid in the chain that forked. An issue also present in EIP-1344. + +This is simply a natural consequence of using chainID as the only anti-replay information for L2 messages. But this can indeed be an issue if the hardfork is created by a small minority. In that case if the majority ignore the fork and do not update its chainID, then all new message from the majority chain (until they update their chainID) can be replayed on the minority-led hardfork since the majority's current chainID is also part of the minority-led fork's chainID history. + +To fix this, every message could specify the block number representing the time it was signed. The contract could then verify that chainID specified as part of that message was valid at that particular block. + + +While EIP-1344 can't do that accurately as the caching system might leave a gap, this proposal can solve it if it is modified to return the blockNumber at which a chainID become invalid. Unfortunately, this would be easy for contracts to not perform that check. And since it suffice of only one important applications to not follow this procedure to put the minority-led fork at a disadvantage, this would fail to achieve the desired goal of protecting the minority-led fork from replay. + +Since a minority-led fork ignored by the majority means that the majority will not keep track of the messages to be submitted (state channel, ...), if such fork get traction later, this would be at the expense of majority users who were not aware of it. As such this proposal assume that minority-led fork will not get traction later and thus do not require to be protected. + +## Test Cases +TBD + +## Implementation +TBD + +## Backwards Compatibility +This EIP is fully backwards compatible with all chains which implement EIP-155 chain ID domain separator for transaction signing. Existing contract are not affected. + +Similarly to EIP-1344, it might be beneficial to update EIP-712 (still in Draft) to deal with chainID separately from the domain separator. Indeed since chainID is expected to change, if the domain separator include chainID, it would have to be dynamically computed. A caching mechanism could be used by smart contract instead though. + +## References +This was previously suggested as part of [EIP-1344 discussion](https://ethereum-magicians.org/t/eip-1344-add-chain-id-opcode/1131/39). + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/EIPS/eip-1962.md b/EIPS/eip-1962.md new file mode 100644 index 0000000000000..93a6937c8af9a --- /dev/null +++ b/EIPS/eip-1962.md @@ -0,0 +1,225 @@ +--- +eip: 1962 +title: EC arithmetic and pairings with runtime definitions +author: Alex Vlasov (@shamatar) +discussions-to: https://ethereum-magicians.org/t/generalised-precompile-for-elliptic-curve-arithmetics-and-pairings-working-group/3208/2 +type: Standards Track +category: Core +status: Draft +created: 2019-04-22 +requires: 1109 +--- + +# Simple summary + +This proposal is an extension and formalization of [EIP1829](https://eips.ethereum.org/EIPS/eip-1829) with an inclusion of pairings. [EIP1109](https://eips.ethereum.org/EIPS/eip-1109) is required due to low cost of some operations compared to the `STATICCALL` opcode (more information in the corresponding section below). + +## Abstract + +This EIP proposes a new precompile to bring cryptographic functionality desired for privacy and scaling solutions. Functionality of such precompile will require the following: + +- Implementation the following operations over elliptic curves in the Weierstrass form with curve parameters such as base field, A, B coefficients defined in runtime: + - Point addition + - Multiplication of a single point over a scalar + - Multiexponentiation +- Implementation pairing operation over elliptic curves from the following "families" with parameters such as base field, extension tower structure, coefficients defined in runtime: + - BLS12 + - BN + - MNT4/6 +- Implementation pairing operation over elliptic curves found by Cocks-Pinch method. Limit k <= 8. + +Full functionality of the precompile is described below in `Specification` section. + +## Motivation + +- There is a pending proposal to implement base elliptic curve arithmetic is covered by [EIP1829](https://eips.ethereum.org/EIPS/eip-1829) and will allow to implement various privacy-preserving protocols with a reasonable gas costs per operation. +- Pairings are an important extension for basic arithmetic and so this new precompile is proposed with the following benefits: + - Extended set of curves will be available to allow Ethereum users to choose their security parameters and required functionality. + - Generic approach of this precompile will allow Ethereum users to experiment with newly found curves of their choice and new constructions constructions without waiting for new forks. + - EC arithmetic is indeed re-implemented in this precompile, but it's strictly required. Most of the pairing-based protocols still need to perform standard EC multiplications or additions and thus such operations must be available on generic set of curves. +- Gas costs - this EIP is designed to estimate gas-cost of performed operation as early as possible during the call and base if solely on specified parameters and operation type. This is a strict requirement for any precompile to allow Ethereum nodes to efficiently reject transactions and operations as early as possible. + +Functionality of this newly proposed precompile is different from [EIP1829](https://eips.ethereum.org/EIPS/eip-1829) in the following aspects: +- Operation on arbitrary-length modulus (up to some upper-limit) for a base field and scalar field of the curve +- Pairing operations are introduced +- Different ABI due to variable parameter length + +## Specification + +If `block.number >= XXXXX`, define a new precompile with an address `0x..` and the following functionality. + +This specification will not yet provide concrete numbers for every operation, but will first introduce interfaces and gas calculation approaches. + +In every call to the precompile the first byte specifies an operation that should be performed: +- `0x01`: Point addition +- `0x02`: Single point multiplication +- `0x03`: Multiexponentiation +- `0x04`: Pairing + +For parameter encoding there is no dense bit packing. All the parameters (sizes, scalars, field elements, etc.) are Big Endian (BE) encoded unsigned integers. + +Points are always encoded in affine coordinates as `(x, y)`. Extension field elements are always encoded as `(c0, c1, c2, ...)` where the element itself is interpreted as `c0 + c1 * u + c2 * u^2 + ...`. + +During the execution all the parameters that should be interpreted as "points" are first checked that those are "on curve", otherwise error is thrown. + +Maximum proposed field bit size is 1023 bits. + +### Binary interface for non-pairing operations + +Every operation of such kind should specify curve parameters right after the "operation" byte: +- 1 byte that encodes byte size of the modulus for a base field. Will be referred as "field element length". +- BE encoded modulus. Field modulo this parameter is referred as the "base field". +- BE encoded parameter `A` for a curve in the Weierstrass form. May be zero but still must take the whole field element length. Must be less than modulus, no reduction should be performed by the precompile. +- BE encoded parameter `B` for a curve in the Weierstrass form. May be zero but still must take the whole field element length. Must be less than modulus, no reduction should be performed by the precompile. +- 1 byte that encodes byte size of the main group on the curve (over which arithmetic should happen). Will be referred as "scalar element length". +- BE encoded size of the main group. Will be referred as "scalar field size". + +While "scalar field size" is not used anywhere in principal operations (point additions, multiplications, multiexponentiations) do not depend on it, this parameter is required to calculate a gas cost for this operation (that's not true for point addition, but interface should be kept universal). E.g. for a naive "double and add" point multiplication approach the worst case scenario is when "add" operation is performed as many times a possible, it can be estimated as if the scalar had the same bit length as a size of the main group, but consisted of only `1` in it's bit decomposition. + +#### Point addition + +After the curve parameters (from above) two points must be specified to perform an addition. Output is a point in affine coordinates. + +#### Point multiplication + +After the curve parameters (from above) one point and one scalar must be specified to perform a multiplication. Output is a point in affine coordinates. Scalar must be less than the size of the group, otherwise error is thrown. + +#### Multiexponentiation + +After the curve parameters (from above) a list of `N` pairs `(point, scalar)` must be specified to perform a multiexponentiation. Output is a point in affine coordinates. Scalars must be less than the size of the group, otherwise error is thrown. For efficiency reasons this operations should use Peppinger algorithm with huge performance benefits. + +#### Gas calculation for non-pairing operations + +For all the operations above arithmetic is performed in a field specified by modulus. Number of operations for point addition is known beforehand, so the bit length (or byte length, more likely) of the modulus clearly must be one of the parameters. Second parameter is length of the bit (or byte) length of the scalar field. Third parameter is number of `(point, scalar)` pairs for multiexponentiation. + +Let's denote field element byte length as `fe_length`, +scalar length as `scalar_length` and number of points as `N`. Concrete coefficients that are to be determined will be labeled as `C_*`. Notation `quadratic` is to indicate a function that is quadratic over it's parameter. + +Quadratic dependency over field element byte length is due to multiplication. + +Proposed formulas: +- Point addition: `C_0*quadratic(fe_length)` +- Point multiplication: `C_1 * quadratic(fe_length) * scalar_length` +- Multiexponentiation: `C_2 * N * quadratic(fe_length) * scalar_length` + +Multiexponentiation formula is different due to use of the specialized algorithm. + +### Binary interface for pairing operations + +Pairing operations have other parameters required to estimate gas costs, so common part of the interface is different from non-pairing operations + +- 1 byte that encodes byte size of the modulus for a base field. Will be referred as "field element length". +- BE encoded modulus. Field modulo this parameter is referred as the "base field". +- BE encoded parameter `A` for a curve in the Weierstrass form. May be zero but still must take the whole field element length. Must be less than modulus, no reduction should be performed by the precompile. +- BE encoded parameter `B` for a curve in the Weierstrass form. May be zero but still must take the whole field element length. Must be less than modulus, no reduction should be performed by the precompile. +- 1 byte that encodes curve "family" + - `0x01` BLS12 + - `0x02` BN + - `0x03` MNT4 + - `0x04` MNT6 + - `0x05` Cocks-Pinch (Tate pairing) + +Parameters for a pairing are encoded as a list of `N` pairs `(p1, p2)` with `p1` being point from `G1` (curve over base field) in affine coordinates, and `p2` being point from `G2` (over the extension). + +Pairing operation consists of two major contributors: +- Miller loop. This part does depend from the number of pairs `N` and has number of steps that is specific for every curve family. For example, BLS12 family is generated by a single scalar `x` (standard notation) that determines number of steps in this loop. Any such parameters must be provided in the binary interface for gas costs estimation. +- Final exponentiation. This part does not depend from the number of pairs. Length of the loop for this operation is different for different families and can either be calculated in from other parameters or specified in the interface. In any case, gas costs can be estimated upfront. + +Below there will be proposed interface for BLS12 family of curves with other interfaces being built in a similar manner. + +#### BLS12 family pairing operation interface + +- 1 byte, length of the `x` parameter. +- BE encoding of parameter `x` (unsigned). +- 1 byte, sign of parameter `x`. `0x00` is `+`, `0x01` is `-`. +- 1 byte, specifies type of the pairing. Either `0x01` or `0x02`. This type depends of the curve and does not affect the gas cost. +- structure of the extension tower: + - non-residue for Fp2 extension in BE encoding. This is just a single element in the base field and must be less than modulus. + - non-residue for Fp6 extension (that is "3 over 2"). This is an element in Fp2 and encoded using the rules from the beginning of this EIP. +- Encoding of the "A" parameter in Fp2 for the curve over the extension (Fp2). +- Encoding of the "B" parameter in Fp2 for the curve over the extension (Fp2). + +For BLS12 family `x` parameter is enough for gas costs estimation. It's Hamming weight and bit length determines complexity of the Miller loop. Final exponentiation depends of the base field size. + +Proposed gas cost formula: `C_0 * quadratic(fe_length) + N * C_1 * fe_length * Hamming_and_bit_length(x)` + +#### Pairing operation interface for other families + +Complexity for BN family is also determined by the single scalar parameter, so interface will be similar to BLS12. For MNT4/6 and Cocks-Pinch curves there would be required to specify number of steps in the Miller loop explicitly in the interface. + +### Possible simplifications + +Due to high complexity of the proposed operations in the aspects of implementation, debugging and evaluation of the factors for gas costs it may be appropriate to either limit the set of curves at the moment of acceptance to some list and then extend it. Another approach (if it's technically possible) would be to have the "whilelist" contract that can be updated without consensus changes (w/o fork). + +In the case of limited set of curve the following set is proposed as a minimal: +- BN254 curve from the current version of Ethereum +- BN curve from DIZK with 2^32 roots of unity +- BLS12-381 +- BLS12-377 from ZEXE with large number of roots of unity +- MNT4/6 cycle from the original [paper](https://eprint.iacr.org/2014/595.pdf). It's not too secure, but may give some freedom for experiments. +- MNT4/6 cycle from Coda if performance allows +- Set of CP generated curves that would allow embedding of BLS12-377 and may be some BN curve that would have large power of two divisor for both base field and scalar field modulus (example of CP curve for BLS12-377 can be found in ZEXE). + +## Rationale + +Only the largest design decisions will be covered: +- While there is no arithmetic over the scalar field (which is modulo size of the main group) of the curve, it's required for gas estimation purposes. +- One may separate interfaces for additions, multiplications and multiexponentiations and estimate gas costs differently for every operation, but it would bring confusion for users and will make it harder to use a precompile from the smart-contract. +- Multiexponentiation is a separate operation due to large cost saving +- There are no point decompressions due to impossibility to get universal gas estimation of square root operation. For a limited number of "good" cases prices would be too different, so specifying the "worst case" is expensive and inefficient, while introduction of another level if complexity into already complicated gas costs formula is not worth is. + +### This precompile and EIP 1109 + +While there is no strict requirement of EIP 1109 for functionality, here is an example why it would be desired: +- BLS12-381 curve, 381 bit modulus, 255 bit scalar field, no native arithmetic is available in EVM for this +- Point addition would take 5000ns (quite overestimated) +- Point multiplication would take roughly 150000ns +- Crude gas schedule 15 Mgas/second from ECRecover precompile +- Point addition would cost 75 gas, with `STATICCALL` adding another 700 +- Point multiplication would cost 2250 gas +- One should also add the cost of memory allocation that is at least `1 + 1 + 48 + 48 + 48 + 1 + 32 + 2*48 + 2*48 = 371 byte` that is around 12 native Ethereum "words" and will require extra 36 gas (with negligible price for memory extension) + +Based on these quite crude estimations one can see that `STATICCALL` price will dominate the total cost (in case of addition) or bring significant overhead (in case of multiplication operation) in case of calls to this precompile. + + +## Backwards Compatibility + +This change is not backwards compatible and requires hard fork to be activated. + +Functionality of the new precompile itself does not affect any existing functionality of Ethereum or EVM. + +This precompile may serve as a complete replacement of the current set of `ECADD`, `ECMUL` and pairing check precompiles (`0x06`, `0x07`, `0x08`) + +## Test Cases +Test cases are the part of the implementation with a link below. + +## Implementation +There is an ongoing implementation effort [here](https://github.com/matter-labs/eip1829). Right now: +- Non-pairing operations are implemented and tested. +- BLS12 family is completed and tested for BLS12-381 and BLS12-377 curves. +- BN family is completed and tested with BN254 curve. +- Cocks-Pinch method curve is tested for k=6 curve from ZEXE. + +## Preliminary benchmarks + +cp6 in benchmarks is a Cocks-Pinch method curve that embeds BLS12-377. Machine: Core i7, 2.9 GHz. + +Multiexponentiation benchmarks take 100 pairs `(generator, random scalar)` as input. Due to the same "base" it may be not too representative benchmark and will be updated. + +``` +test pairings::bls12::tests::bench_bls12_381_pairing ... bench: 2,348,317 ns/iter (+/- 605,340) +test pairings::cp::tests::bench_cp6_pairing ... bench: 86,328,825 ns/iter (+/- 11,802,073) +test tests::bench_addition_bn254 ... bench: 388 ns/iter (+/- 73) +test tests::bench_doubling_bn254 ... bench: 187 ns/iter (+/- 4) +test tests::bench_field_inverse ... bench: 2,478 ns/iter (+/- 167) +test tests::bench_field_mont_inverse ... bench: 2,356 ns/iter (+/- 51) +test tests::bench_multiplication_bn254 ... bench: 81,744 ns/iter (+/- 6,984) +test tests::bench_multiplication_bn254_into_affine ... bench: 81,925 ns/iter (+/- 3,323) +test tests::bench_multiplication_bn254_into_affine_wnaf ... bench: 74,716 ns/iter (+/- 4,076) +test tests::bench_naive_multiexp_bn254 ... bench: 10,659,911 ns/iter (+/- 559,790) +test tests::bench_peppinger_bn254 ... bench: 2,678,743 ns/iter (+/- 148,914) +test tests::bench_wnaf_multiexp_bn254 ... bench: 9,161,281 ns/iter (+/- 456,137) +``` + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/EIPS/eip-1965.md b/EIPS/eip-1965.md new file mode 100644 index 0000000000000..aad5ea94dd499 --- /dev/null +++ b/EIPS/eip-1965.md @@ -0,0 +1,63 @@ +--- +eip: 1965 +title: Method to check if a chainID is valid at a specific block Number +author: Ronan Sandford (@wighawag) +category: Core +type: Standards Track +discussions-to: https://ethereum-magicians.org/t/eip-1965-valid-chainid-for-specific-blocknumber-protect-all-forks/3181 +status: Draft +created: 2019-04-20 +requires: 155 +--- + +## Abstract +This EIP adds a precompile that returns whether a specific chainID (EIP-155 unique identifier) is valid at a specific blockNumber. ChainID are assumed to be valid up to the blockNumber at which they get replaced by a new chainID. + +## Motivation +[EIP-155](https://eips.ethereum.org/EIPS/eip-155) proposes to use the chain ID to prevent the replay of transactions between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling off-chain message signatures, especially for Layer 2 signature schemes using [EIP-712](https://eips.ethereum.org/EIPS/eip-712). + +[EIP-1344](http://eips.ethereum.org/EIPS/eip-1344) is attempting to solve this by giving smart contract access to the tip of the chainID history. This is insuficient as such value is changing. Hence why EIP-1344 describes a contract based solution to work around the problem. It would be better to solve it in a simpler, cheaper and safer manner, removing the potential risk of misuse present in EIP-1344. Furthermore EIP-1344 can't protect replay properly for minority-led hardfork as the caching system cannot guarantee accuracy of the blockNumber at which the new chainID has been introduced. + +[EIP-1959](https://github.com/ethereum/EIPs/pull/1959) solves the issue of EIP-1344 but do not attempt to protect from minority-led hardfork as mentioned in the rationale. We consider this a mistake, since it remove some freedom to fork. We consider that all fork should be given equal oportunities. And while there will always be issues we can't solve for the majority that ignore a particular fork, **users that decide to use both the minority-fork and the majority-chain should be protected from replay without having to wait for the majority chain to update its chainID.** + +## Specification +Adds a new precompile which uses 2 argument : a 32 bytes value that represent the chainID to test and a 32 bytes value representing the blockNumber at which the chainID is tested. It return 0x1 if the chainID is valid at the specific blockNumber, 0x0 otherwise. Note that chainID are considered valid up to the blockNumber at which they are replaced. So they are valid for every blockNumber past their replacement. + +The operation will costs no more than `G_blockhash` + `G_verylow` to execute. This could be lower as chainID are only introduced during hardfork. + +The cost of the operation might need to be adjusted later as the number of chainID in the history of the chain grows. + +Note though that the alternative to keep track of old chainID is to implement a smart contract based caching solution as EIP-1344 proposes comes with an overall higher gas cost and exhibit issues for minority-led hardfork (see Rationale section below). As such the gas cost is simply a necessary cost for the feature. + +## Rationale + +The rationale at EIP-1959 applies here as well too : + +- An opcode is better than a caching system for past chainID, It is cheaper, safer and do not include gaps. +- Direct access to the latest chainID is dangerous since it make it easy for contract to use it as a replay protection mechanism while preventing otherwise valid old messages to be valid after a fork that change the chainID. This can have disastrous consequences on users. +- all off-chain messaged signed before a fork should be valid across all side of the fork. + +The only difference is that this current proposal propose a solution to protect hardfork led by a minority. + +To summarize there is 2 possible fork scenario : + +1) The majority decide to make an hardfork but a minority disagree with it (ETC is such example). The fork is planned for block X. If the majority is not taking any action to automate the process of assigning a different chainID for both, the minority has plenty of time to plan for a chainID upgrade to happen at that same block X. Now if they do not do it, their users will face the problem that their messages will be replayable on the majority chain (Note that this is not true the other way around as we assume the majority decided to change the chainID). As such there is no reason that they’ll leave it that way. + +2) A minority decide to create an hardfork that the majority disagree with (or simply ignore). Now, the same as above can happen but since we are talking about a minority there is a chance that the majority do not care about the minority. In that case, there would be no incentive for the majority to upgrade the chainID. This means that user of both side of the fork will have the messages meant for the majority chain replayable on the minority-chain (even if this one changed its chainID) unless extra precaution is taken. + +The solution is to add the blockNumber representing the time at which the message was signed and use it as an argument to the opcode proposed here. This way, when the minority forks with a new chainID, the previous chainID become invalid from that time onward. So new messages destinated to the majority chain can't be replayed on the minority fork. + + +## Backwards Compatibility + +EIP-712 is still in draft but would need to be updated to include the blockNumber as part of the values that wallets need to verify for the protection of their users. + +Since chainID and blockNumber will vary, they should not be part of the domain separator (meant to be generated once) but another part of the message. + +While the pair could be optional for contract that do not care about replays or have other ways to prevent them, if chainID is present, the blockNumber must be present too. And if any of them is present, wallet need to ensure that the chainID is indeed the latest one of the chain being used, while the blockNumber is the latest one at the point of signing. During fork transition, the wallet can use the blockNumber to know which chainID to use. + +## References +This was previously suggested as part of [EIP1959 discussion](https://ethereum-magicians.org/t/eip-1959-valid-chainid-opcode/3170). + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/EIPS/eip-1967.md b/EIPS/eip-1967.md new file mode 100644 index 0000000000000..5df3f5f908312 --- /dev/null +++ b/EIPS/eip-1967.md @@ -0,0 +1,78 @@ +--- +eip: 1967 +title: Standard Proxy Storage Slots +author: Santiago Palladino (@spalladino) +discussions-to: https://ethereum-magicians.org/t/eip-1967-standard-proxy-storage-slots/3185 +status: Draft +type: Standards Track +category: ERC +created: 2019-04-24 +--- + + + +## Simple Summary + +Standardise how proxies store the address of the logic contract they delegate to, and other proxy specific information. + +## Abstract + +Delegating **proxy contracts** are widely used for both upgradeability and gas savings. These proxies rely on a **logic contract** (also known as implementation contract or master copy) that is called using `delegatecall`. This allows proxies to keep a persistent state (storage and balance) while the code is delegated to the logic contract. + +To avoid clashes in storage usage between the proxy and logic contract, the address of the logic contract is typically saved in a [specific storage slot](https://blog.zeppelinos.org/upgradeability-using-unstructured-storage/) guaranteed to be never allocated by a compiler. This EIP proposes a set of standard slots to store proxy information. This allows clients like block explorers to properly extract and show this information to end users, and logic contracts to optionally act upon it. + +## Motivation + +Delegating proxies are widely in use, as a means to both support upgrades and reduce gas costs of deployments. Examples of these proxies are found in [ZeppelinOS](https://blog.zeppelinos.org/the-transparent-proxy-pattern/), [Terminal](https://medium.com/terminaldotco/escape-hatch-proxy-efb681de108d), [Gnosis](https://blog.gnosis.pm/solidity-delegateproxy-contracts-e09957d0f201), [AragonOS](https://github.com/aragon/aragonOS/blob/dev/contracts/common/DelegateProxy.sol), [Melonport](https://github.com/melonproject/melon-mail/blob/782aeff9418ac8cdd80875fd6c400bf96f3b03b3/solidity/contracts/DelegateProxy.sol), [Limechain](https://github.com/LimeChain/UpgradeableSolidityContract/blob/14bcabc338130fb2aba2ce8bd27b885305566fce/contracts/Upgradeability/Forwardable.sol), [WindingTree](https://github.com/windingtree/upgradeable-token-labs/blob/af3b66096091d8282d5c9c55c33365315d85f3e1/contracts/upgradable/DelegateProxy.sol), [Decentraland](https://github.com/decentraland/land/blob/5154046844f6f94a5074e82abe01381e6fd7c39d/contracts/upgradable/DelegateProxy.sol), and many others. + +However, the lack of a common interface for obtaining the logic address for a proxy makes it impossible to build common tools that act upon this information. + +A classic example of this is a block explorer. Here, the end user wants to interact with the underlying logic contract and not the proxy itself. Having a common way to retrieve the logic contract address from a proxy would allow a block explorer, among other things, to show the ABI of the logic contract and not that of the proxy (see [this proxy](https://etherscan.io/token/0x00fdae9174357424a78afaad98da36fd66dd9e03#readContract) for an example). The explorer should check the storage of the contract at the distinguished slots to determine if it is indeed a proxy, in which case it should show information on both the proxy and the logic contract. + +Another example are logic contracts that explicitly act upon the fact that they are being proxied. This allows them to potentially trigger a code update as part of their logic, as is the case of [Universal Upgradeable Proxy Standard (EIP1822)](https://eips.ethereum.org/EIPS/eip-1822). A common storage slot allows these use cases independently of the specific proxy implementation being used. + +## Specification + +The main requirement for the storage slots chosen is that they must never be picked by the compiler to store any contract state variable. Otherwise, a logic contract could inadvertently overwrite this information on the proxy when writing to a variable of its own. + +[Solidity](https://solidity.readthedocs.io/en/v0.4.21/miscellaneous.html#layout-of-state-variables-in-storage) maps variables to storage based on the order in which they were declared, after the contract inheritance chain is linearized: the first variable is assigned the first slot, and so on. The exception are values in dynamic arrays and mappings, which are stored in the hash of the concatenation of the key and the storage slot. The Solidity development team has [confirmed](https://twitter.com/ethchris/status/1073692785176444928) that the storage layout is to be preserved among new versions. Vyper seems to [follow the same strategy as Solidity](https://github.com/ethereum/vyper/issues/769). Note that contracts written in other languages, or directly in assembly, may incur in clashes. + +As such, the proposed storage slots for proxy-specific information are the following. They are chosen in such a way so they are guaranteed to not clash with state variables allocated by the compiler, since they depend on the hash of a string that does not start with a storage index. Furthermore, a `-1` offset is added so the preimage of the hash cannot be known, further reducing the chances of a possible attack. + +More slots for additional information can be added in subsequent ERCs as needed. + +### Logic contract address + +Storage slot `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` +(obtained as `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)`). + +Holds the address of the logic contract that this proxy delegates to. + +### Admin address + +Storage slot `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` +(obtained as `bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)`). + +Holds the address that is allowed to upgrade the logic contract address for this proxy (optional). + +## Rationale + + +This EIP standardises the **storage slot** for the logic contract address, instead of a public method on the proxy contract as [DelegateProxy (EIP897)](https://eips.ethereum.org/EIPS/eip-897) does. The rationale for this is that proxies should never expose functions to end users that could potentially clash with those of the logic contract. + +Note that a clash may occur even among functions with different names, since the ABI relies on just four bytes for the function selector. This can lead to unexpected errors, or even exploits, where a call to a proxied contract returns a different value than expected, since the proxy intercepts the call and answers with a value of its own. + +From [_Malicious backdoors in Ethereum proxies_](https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357) by Nomic Labs: + +> Any function in the Proxy contract whose selector matches with one in the implementation contract will be called directly, completely skipping the implementation code. +> +> Because the function selectors use a fixed amount of bytes, there will always be the possibility of a clash. This isn’t an issue for day to day development, given that the Solidity compiler will detect a selector clash within a contract, but this becomes exploitable when selectors are used for cross-contract interaction. Clashes can be abused to create a seemingly well-behaved contract that’s actually concealing a backdoor. + +The fact that proxy public functions are potentially exploitable makes it necessary to standardise the logic contract address in a different way. This approach is also used as part of [Universal Upgradeable Proxy Standard (EIP1822)](https://eips.ethereum.org/EIPS/eip-1822), which could become a specialization of this EIP. + +## Implementation + +Sample proxy implementations that follow this standard can be found in the [ZeppelinOS repository](https://github.com/zeppelinos/zos/blob/dc9e4ed/packages/lib/contracts/upgradeability/BaseUpgradeabilityProxy.sol), albeit with a different set of slots. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1973.md b/EIPS/eip-1973.md new file mode 100644 index 0000000000000..64c7a9cf15cb6 --- /dev/null +++ b/EIPS/eip-1973.md @@ -0,0 +1,271 @@ +--- +eip: 1973 +title: Scalable Rewards +author: Lee Raj (@lerajk), Qin Jian (@qinjian) +type: Standards Track +category: ERC +status: Draft +created: 2019-04-01 +--- + +## Simple Summary + + A mintable token rewards interface that mints 'n' tokens per block which are distributed equally among the 'm' participants in the DAPP's ecosystem. + +## Abstract + + The mintable token rewards interface allows DApps to build a token economy where token rewards are distributed equally among the active participants. The tokens are minted based on per block basis that are configurable (E.g. 10.2356 tokens per block, 0.1 token per block, 1350 tokens per block) and the mint function can be initiated by any active participant. The token rewards distributed to each participant is dependent on the number of participants in the network. At the beginning, when the network has low volume, the tokens rewards per participant is high but as the network scales the token rewards decreases dynamically. + + + ## Motivation + +Distributing tokens through a push system to a large amount of participants fails due to block gas limit. As the number of participants in the network grow to tens of thousands, keeping track of the iterable registry of participants and their corresponding rewards in a push system becomes unmanagable. E.g. Looping through 5000 addresses to distribute 0.0000001 reward tokens is highly inefficient. Furthermore, the gas fees in these transactions are high and needs to be undertaken by the DApp developer or the respective company, leading to centralization concerns. + +A pull system is required to keep the application completely decentralized and to avoid the block gas limit problem. However, no standard solution has been proposed to distribute scalable rewards to tens of thousands participants with a pull system. This is what we propose with this EIP through concepts like TPP, round mask, participant mask. + +## Specification + +### Definitions + + `token amount per participant in the ecosytem or TPP (token per participant)`: TPP = (token amount to mint / total active participants) + + `roundMask`: the cumulative snapshot of TPP over time for the token contract. E.g. transactionOne = 10 tokens are minted with 100 available participants (TPP = 10 / 100) , transactionTwo = 12 tokens are minted with 95 participants (TPP = 12 / 95 ) + + roundMask = (10/100) + (12/95) + + `participantMask`: is used to keep track of a `msg.sender` (participant) rewards over time. When a `msg.sender` joins or leaves the ecosystem, the player mask is updated + + participantMask = previous roundMask OR (current roundMask - TPP) + + `rewards for msg.sender`: roundMask - participantMask + + E.g. Let's assume a total of 6 transactions (smart contract triggers or functions calls) are in place with 10 existing participants (denominator) and 20 tokens (numerator) are minted per transaction. At 2nd transaction, the 11th participant joins the network and exits before 5th transaction, the 11th participant's balance is as follows: + + ``` + t1 roundMask = (20/10) + t2 roundMask = (20/10) + (20/11) + t3 roundMask = (20/10) + (20/11) + (20/11) + t4 roundMask = (20/10) + (20/11) + (20/11) + (20/11) + t5 roundMask = (20/10) + (20/11) + (20/11) + (20/11)+ (20/10) + t6 roundMask = (20/10) + (20/11) + (20/11) + (20/11)+ (20/10) + (20/10) + ``` + + Total tokens released in 6 transactions = 60 tokens + + As the participant joins at t2 and leaves before t5, the participant deserves the rewards between t2 and t4. When the participant joins at t2, the 'participantMask = (20/10)', when the participant leaves before t5, the cumulative deserved reward tokens are : + + rewards for msg.sender: `[t4 roundMask = (20/10) + (20/11)+ (20/11) + (20/11)] - [participantMask = (20/10)] = [rewards = (20/11)+ (20/11) + (20/11)]` + + When the same participant joins the ecosystem at a later point (t27 or t35), a new 'participantMask' is given that is used to calculate the new deserved reward tokens when the participant exits. This process continues dynamically for each participant. + + `tokensPerBlock`: the amount of tokens that will be released per block + + `blockFreezeInterval`: the number of blocks that need to pass until the next mint. E.g. if set to 50 and 'n' tokens were minted at block 'b', the next 'n' tokens won't be minted until 'b + 50' blocks have passed + + `lastMintedBlockNumber`: the block number on which last 'n' tokens were minted + + `totalParticipants` : the total number of participants in the DApp network + + `tokencontractAddress` : the contract address to which tokens will be minted, default is address(this) + +``` +SOLIDITY + +pragma solidity ^0.5.2; + +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"; + +contract Rewards is ERC20Mintable, ERC20Detailed { + +using SafeMath for uint256; + +uint256 public roundMask; +uint256 public lastMintedBlockNumber; +uint256 public totalParticipants = 0; +uint256 public tokensPerBlock; +uint256 public blockFreezeInterval; +address public tokencontractAddress = address(this); +mapping(address => uint256) public participantMask; + +/** + * @dev constructor, initializes variables. + * @param _tokensPerBlock The amount of token that will be released per block, entered in wei format (E.g. 1000000000000000000) + * @param _blockFreezeInterval The amount of blocks that need to pass (E.g. 1, 10, 100) before more tokens are brought into the ecosystem. + */ + constructor(uint256 _tokensPerBlock, uint256 _blockFreezeInterval) public ERC20Detailed("Simple Token", "SIM", 18){ +lastMintedBlockNumber = block.number; +tokensPerBlock = _tokensPerBlock; +blockFreezeInterval = _blockFreezeInterval; +} + +/** + * @dev Modifier to check if msg.sender is whitelisted as a minter. + */ +modifier isAuthorized() { +require(isMinter(msg.sender)); +_; +} + +/** + * @dev Function to add participants in the network. + * @param _minter The address that will be able to mint tokens. + * @return A boolean that indicates if the operation was successful. + */ +function addMinters(address _minter) external returns (bool) { +_addMinter(_minter); +totalParticipants = totalParticipants.add(1); +updateParticipantMask(_minter); +return true; +} + + +/** + * @dev Function to remove participants in the network. + * @param _minter The address that will be unable to mint tokens. + * @return A boolean that indicates if the operation was successful. + */ +function removeMinters(address _minter) external returns (bool) { +totalParticipants = totalParticipants.sub(1); +_removeMinter(_minter); +return true; +} + + +/** + * @dev Function to introduce new tokens in the network. + * @return A boolean that indicates if the operation was successful. + */ +function trigger() external isAuthorized returns (bool) { +bool res = readyToMint(); +if(res == false) { +return false; +} else { +mintTokens(); +return true; +} +} + +/** + * @dev Function to withdraw rewarded tokens by a participant. + * @return A boolean that indicates if the operation was successful. + */ +function withdraw() external isAuthorized returns (bool) { +uint256 amount = calculateRewards(); +require(amount >0); +ERC20(tokencontractAddress).transfer(msg.sender, amount); +} + +/** + * @dev Function to check if new tokens are ready to be minted. + * @return A boolean that indicates if the operation was successful. + */ +function readyToMint() public view returns (bool) { +uint256 currentBlockNumber = block.number; +uint256 lastBlockNumber = lastMintedBlockNumber; +if(currentBlockNumber > lastBlockNumber + blockFreezeInterval) { +return true; +} else { +return false; +} +} + +/** + * @dev Function to calculate current rewards for a participant. + * @return A uint that returns the calculated rewards amount. + */ +function calculateRewards() private returns (uint256) { +uint256 playerMask = participantMask[msg.sender]; +uint256 rewards = roundMask.sub(playerMask); +updateParticipantMask(msg.sender); +return rewards; +} + +/** + * @dev Function to mint new tokens into the economy. + * @return A boolean that indicates if the operation was successful. + */ +function mintTokens() private returns (bool) { +uint256 currentBlockNumber = block.number; +uint256 tokenReleaseAmount = (currentBlockNumber.sub(lastMintedBlockNumber)).mul(tokensPerBlock); +lastMintedBlockNumber = currentBlockNumber; +mint(tokencontractAddress, tokenReleaseAmount); +calculateTPP(tokenReleaseAmount); +return true; +} + + /** +* @dev Function to calculate TPP (token amount per participant). +* @return A boolean that indicates if the operation was successful. +*/ +function calculateTPP(uint256 tokens) private returns (bool) { +uint256 tpp = tokens.div(totalParticipants); +updateRoundMask(tpp); +return true; +} + + /** +* @dev Function to update round mask. +* @return A boolean that indicates if the operation was successful. +*/ +function updateRoundMask(uint256 tpp) private returns (bool) { +roundMask = roundMask.add(tpp); +return true; +} + + /** +* @dev Function to update participant mask (store the previous round mask) +* @return A boolean that indicates if the operation was successful. +*/ +function updateParticipantMask(address participant) private returns (bool) { +uint256 previousRoundMask = roundMask; +participantMask[participant] = previousRoundMask; +return true; +} + +} +``` + +## Rationale + +Currently, there is no standard for a scalable reward distribution mechanism. In order to create a sustainable cryptoeconomic environment within DAPPs, incentives play a large role. However, without a scalable way to distribute rewards to tens of thousands of participants, most DAPPs lack a good incentive structure. The ones with a sustainable cryptoeconomic environment depend heavily on centralized servers or a group of selective nodes to trigger the smart contracts. But, in order to keep an application truly decentralized, the reward distribution mechanism must depend on the active participants itself and scale as the number of participants grow. This is what this EIP intends to accomplish. + +## Backwards Compatibility + +Not Applicable. + +## Test Cases + +WIP, will be added. + +## Implementation + +WIP, a proper implementation will be added later.A sample example is below: + +`etherscan rewards contract` : https://ropsten.etherscan.io/address/0x8b0abfc541ab7558857816a67e186221adf887bc#tokentxns + +`Step 1` : deploy Rewards contract with the following parameters_tokensPerBlock = 1e18, _blockFreezeInterval = 1 + +`Step 2` : add Alice(0x123) and Bob(0x456) as minters, addMinters(address _minter) + +`Step 3` : call trigger() from Alice / Bob's account. 65 blocks are passed, hence 65 SIM tokens are minted. The RM is 32500000000000000000 + +`Step 4` : Alice withdraws and receives 32.5 SIM tokens (65 tokens / 2 participants) and her PM = 32500000000000000000 + +`Step 5` : add Satoshi(0x321) and Vitalik(0x654) as minters, addMinters(address _minter) + +`Step 6` : call trigger() from Alice / Bob's / Satoshi / Vitalik account. 101 blocks are passed, hence 101 SIM tokens are minted. The RM is 57750000000000000000 + +`Step 7` : Alice withdraws and receives 25.25 SIM tokens (101 tokens / 4 participants) and her PM = 57750000000000000000 + +`Step 8` : Bob withdraws and receives 57.75 SIM tokens ((65 tokens / 2 participants) + (101 tokens / 4 participants)). Bob's PM = 57750000000000000000 + +## Copyright + +Copyright and related rights waived via CC0. + +## References + +1. Scalable Reward Distribution on the Ethereum Blockchain by Bogdan Batog, Lucian Boca and Nick Johnson + +2. Fomo3d DApp, https://fomo3d.hostedwiki.co/ \ No newline at end of file diff --git a/EIPS/eip-1985.md b/EIPS/eip-1985.md new file mode 100644 index 0000000000000..a2787c6219d54 --- /dev/null +++ b/EIPS/eip-1985.md @@ -0,0 +1,122 @@ +--- +eip: 1985 +title: Sane limits for certain EVM parameters +author: Alex Beregszaszi (@axic), Paweł Bylica (@chfast) +discussions-to: https://ethereum-magicians.org/t/eip-1985-sane-limits-for-certain-evm-parameters/3224 +status: Draft +type: Standards Track +category: Core +created: 2018-08-01 +--- + +## Abstract + +Introduce an explicit value range for certain EVM parameters +(such as gas limit, block number, block timestamp, size field when returning/copying data within EVM). +Some of these already have an implicit value range due to various (practical) reasons. + +## Motivation + +Having such an explicit value range can help in creating compatible client implementations, +in certain cases it can also offer minor speed improvements, +and can reduce the effort needed to create consensus critical test cases +by eliminating unrealistic edge cases. + +## Specification + +If `block.number >= {FORK_BLOCK}`, the following value ranges are introduced. +They restrict the results (i.e. values pushed to the stack) of the instructions listed below. + +1. *gas*, *gas limit*, *block gas limit* + is a range between `0` and `0x7fffffffffffffff` (`2**63 - 1`, `9223372036854775807`). + It affects the following instructions: + - `GASLIMIT` (`0x45`), + - `GAS` (`0x5a`). + +2. *block number*, *timestamp* + is a range between `0` and `0x7fffffffffffffff` (`2**63 - 1`, `9223372036854775807`). + It affects the following instructions: + - `TIMESTAMP` (`0x42`), + - `NUMBER` (`0x43`). + +3. *account address* + is a range between `0` and `0xffffffffffffffffffffffffffffffffffffffff` (`2**160 - 1`, `1461501637330902918203684832716283019655932542975`) + i.e. the address occupies the 160 low bits of the 256-bit value and the remaining top 96 bits must be zeros. + It affects the following instructions: + - `ADDRESS` (`0x30`), + - `ORIGIN` (`0x32`), + - `CALLER` (`0x33`), + - `COINBASE` (`0x41`), + - `CREATE` (`0xf0`), + - `CREATE2` (`0xf5`). + +4. *buffer size* + is a range between `0` and `0xffffffff` (`2**32 - 1`, `4294967295`). + It affects the following instructions: + - `CALLDATASIZE` (`0x36`), + - `CODESIZE` (`0x38`), + - `EXTCODESIZE` (`0x3b`), + - `RETURNDATASIZE` (`0x3d`), + - `MSIZE` (`0x59`). + + +## Rationale + +These limits have been: +- proposed by [EVMC] +- implemented partially by certain clients, such as [Aleth], [geth], [Parity] and [ethereumjs] +- allowed by certain test cases in the [Ethereum testing suite] +- and implicitly also allowed by certain assumptions, such as due to gas limits some of these values cannot grow past a certain limit + +Most of the limits proposed in this document have been previously explored and tested in [EVMC]. + +Using the `2**63 - 1` constant to limit some of the ranges: +- allows using signed 64-bit integer type to represent it, + what helps programming languages not having unsigned types, +- makes arithmetic simpler (e.g. checking out-of-gas conditions is simple as `gas_counter < 0`). + +### Timestamp + +The [Yellow Paper] defines the timestamp in block as "A scalar value equal to the reasonable output of Unix’s time() at this block’s inception". +IEEE Std 1003.1-2001 (POSIX.1) leaves that definition implementation defined. + +### Addresses + +The size of addresses is specified in the [Yellow Paper] as 20 bytes. +E.g. the `COINBASE` instruction is specified to return *H*c ∈ 𝔹20 which has 20 bytes. + +### Comparing current implementations + +- Timestamp is implemented as a 64-bit value in [Aleth], [geth] and [Parity] +- Block gas limit is implemented as a 64-bit in [Aleth] and [geth] + +## Backwards Compatibility + +All of these limits are already enforced mostly through the block gas limit. Since the out of range case results in a transaction failure, there should not be a change in behaviour. + +## Test Cases + +TBA + +## Implementation + +TBA + +## References + +[EIP-106](https://github.com/ethereum/EIPs/issues/106) proposed the block gas limit to be limited at `2**63 - 1`. + +## TODO + +1. Does the gas limit apply to the gas argument for call instructions? + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[EVMC]: https://github.com/ethereum/evmc +[Aleth]: https://github.com/ethereum/aleth +[geth]: https://github.com/ethereum/go-ethereum +[Parity]: https://github.com/paritytech/parity-ethereum +[ethereumjs]: https://github.com/ethereumjs +[Ethereum testing suite]: https://github.com/ethereum/tests +[Yellow Paper]: https://github.com/ethereum/yellowpaper diff --git a/EIPS/eip-2003.md b/EIPS/eip-2003.md new file mode 100644 index 0000000000000..c5ab43fa18435 --- /dev/null +++ b/EIPS/eip-2003.md @@ -0,0 +1,135 @@ +--- +eip: 2003 +title: EVMC modules for implementations of precompiled contracts +author: Paweł Bylica (@chfast), Alex Beregszaszi (@axic) +discussions-to: https://github.com/ethereum/evmc/issues/259 +status: Draft +type: Standards Track +category: Interface +created: 2019-05-09 +requires: 1352 +--- + +## Abstract + +[EVMC] specifies a generic API for Ethereum execution engines. +This EIP specifies a way of providing implementations of Ethereum precompiled contracts +using the [EVMC VM API]. + + +## Specification + +For the complete [EVMC] specification visit the [EVMC documentation] first. +This EIP is based on and is compatible with EVMC ABI version 6. + +The EVMC module with implementations of precompiled contracts SHOULD: + +1. Advertise the [`EVMC_CAPABILITY_PRECOMPILES`] capability + in the [`get_capabilities()`] method. + +2. Implement the [`execute()`] method in the following way: + + 1. Validate the incoming execution request requirements: + + 1. The message kind ([`evmc_message::kind`]) is a call ([`EVMC_CALL`]). + + 2. The call destination address ([`evmc_message::destination`]) + is within the range of precompiled contracts defined by [EIP-1352]. + + 3. There is no code provided (the `code` argument is `NULL` and `code_size` argument is `0`). + + If the requirements are not fulfilled, abort execution with the [`EVMC_REJECTED`] status code. + + 2. Check if the call destination address ([`evmc_message::destination`]) + targets existing precompiled contract. + Consider the EVM revision ([`evmc_revision`]) requested by + the `rev` parameter of [`execute()`]. + + If yes, execute as follows: + + 1. Inspect the input data ([`evmc_message::input_data`], [`evmc_message::input_size`]) + and calculate the _gas cost_ of the execution. + + 2. Compute the amount of _gas left_ after execution by + subtracting the _gas cost_ from the call gas limit ([`evmc_message::gas`]). + + 3. If _gas left_ is negative, + abort execution with the [`EVMC_OUT_OF_GAS`] status code. + + 4. Otherwise, + execute the code of the precompiled contract, + return the [`EVMC_SUCCESS`] status code, the output and _gas left_ + ([`evmc_result::output_data`], [`evmc_result::output_size`], [`evmc_result::gas_left`]). + + 3. Otherwise, emulate execution of empty code by returning + the [`EVMC_SUCCESS`] status code + and _gas left_ equal the call gas limit ([`evmc_message::gas`]). + +Precompiled contract implementations are allowed to return two more EVMC error codes: +- [`EVMC_FAILURE`] if the failure was caused due to something other than out of gas (e.g. input validation error) +- [`EVMC_REVERT`] if the precompile doesn't want to forfeit all supplied gas (as of May 2019 no such precompile exists) + +The Client is not required to provide the Host interface ([`evmc_context`] argument of [`execute()`] is set to NULL). +Therefore, the precompiled contracts implementation MUST NOT access the `evmc_context`. + + +## Rationale + +It is very unlikely that any precompile will need to access or modify a contract state. +Not requiring the Client to implement the EVMC Host interface removes the big portion of work +needed for full EVMC integration. + + +## Test Cases + +EVMC provides the [evmc-vmtester] tool for checking compatibility with the EVMC specification. + + +## Implementations + +- [Example of Precompiles VM implementation][example_precompiles_vm.cpp] +- [ewasm precompiles] +- Aleth code for precompiles +- Parity code for precompiles +- [EIP-1962 implemented as an EVMC precompile module](https://github.com/axic/eip1962-evmc) + + +## References + +- [EVMC – Ethereum Client-VM Connector API][EVMC] +- [EVMC documentation] +- [EVMC VM Implementation Guide][EVMC VM API] +- [EIP 1352: Specify restricted address range for precompiles/system contracts][EIP-1352] + + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + + +[EIP-1352]: https://eips.ethereum.org/EIPS/eip-1352 +[EVMC]: https://github.com/ethereum/evmc +[EVMC documentation]: https://ethereum.github.io/evmc/ +[EVMC VM API]: https://ethereum.github.io/evmc/vmguide.html +[evmc-vmtester]: https://ethereum.github.io/evmc/vmtester.html +[example_precompiles_vm.cpp]: https://github.com/ethereum/evmc/blob/master/examples/example_precompiles_vm/example_precompiles_vm.cpp +[ewasm precompiles]: https://github.com/ewasm/ewasm-precompiles + +[`EVMC_CALL`]: https://ethereum.github.io/evmc/group__EVMC.html#ggab2fa68a92a6828064a61e46060abc634abcf3ae29d9a88ff70b98374fc665694a +[`EVMC_CAPABILITY_PRECOMPILES`]: https://ethereum.github.io/evmc/group__EVMC.html#gga44f9ecb88cf6422a0072936494fd6ac7a43ea2aa7b099a2d67bc53c118ff3683d +[`EVMC_FAILURE`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920aed5b2a4afa5a47af732569445920a4a9 +[`EVMC_OUT_OF_GAS`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920abfc47f75656c996c0b29c0553c00fc18 +[`EVMC_REJECTED`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920a2f3e0d8777f8d974ead27ae2a6eb2005 +[`EVMC_REVERT`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920aed708e84d49cc1270e54ec20b0ca0a05 +[`EVMC_SUCCESS`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920a4bc3069fec2bab2a55355a72b7db68b7 +[`execute()`]: https://ethereum.github.io/evmc/structevmc__instance.html#a0823ebff21f9b0395b157e8c6b14a207 +[`get_capabilities()`]: https://ethereum.github.io/evmc/structevmc__instance.html#ae63b9ca898aa41cbd1e2fe86ca8f4e1c +[`evmc_message::destination`]: https://ethereum.github.io/evmc/structevmc__message.html#a88ecfaa03a85a31c6da36fa043b98cea +[`evmc_message::input_data`]: https://ethereum.github.io/evmc/structevmc__message.html#a1adee3454b105eb29cd659ee0cf65c77 +[`evmc_message::input_size`]: https://ethereum.github.io/evmc/structevmc__message.html#a2cf1deebd0dbbb20f25ecdfa299f4b5d +[`evmc_message::gas`]: https://ethereum.github.io/evmc/structevmc__message.html#ae8deff46588584fa27890e74c82db5e7 +[`evmc_message::kind`]: https://ethereum.github.io/evmc/structevmc__message.html#a691cb93e81d6dfd4fd7e2fa3d06a6bfa +[`evmc_result::gas_left`]: https://ethereum.github.io/evmc/structevmc__result.html#af8478c93dbcc3cb2876037c5a5afd4c0 +[`evmc_result::output_data`]: https://ethereum.github.io/evmc/structevmc__result.html#a61978e85f9d795a7b9695b9cbf1748d6 +[`evmc_result::output_size`]: https://ethereum.github.io/evmc/structevmc__result.html#a93bb7419aff492cdef754421c6d74e26 +[`evmc_revision`]: https://ethereum.github.io/evmc/group__EVMC.html#gae5759b1590071966ccf6a505b52a0ef7 diff --git a/EIPS/eip-2014.md b/EIPS/eip-2014.md new file mode 100644 index 0000000000000..95c88d908f0e8 --- /dev/null +++ b/EIPS/eip-2014.md @@ -0,0 +1,94 @@ +--- +eip: 2014 +title: Extended State Oracle +author: Alex Beregszaszi (@axic) +discussions-to: https://ethereum-magicians.org/t/eip-2014-extended-state-oracle/3301 +status: Draft +type: Standards Track +category: Core +created: 2019-05-10 +requires: 140 +--- + +## Simple Summary + + +## Abstract + +Introduce a new system contract with an extensible interface following the [Contract ABI Encoding] to access extended data sets, such as chain identifiers, block hashes, etc. + +This allows Ethereum contract languages to interact with this contract as if it were a regular contract and not needing any language support. + +## Motivation + +Over the past couple of years several proposals were made to extend the EVM with more data. Some examples include extended access to block hashes ([EIP-210]) and chain identifiers ([EIP-1344]). + +Adding them as EVM opcodes seems to be using the scarce opcode space for relatively less frequently used features, while adding them as precompiles is perceived as more complicated due to an interface +needs to be defined and agreed on for every case. + +This proposal tries to solve both issues with defining an extensible standard interface. + +## Specification + +A new system contract ("precompile") is introduced at address `0x0000000000000000000000000000000000000009` called ESO (Extended State Oracle). + +It can be queried using `CALL` or `STATICCALL` and follows the [Contract ABI Encoding] for the inputs and outputs. Using elementary types in the ABI encoding is encouraged to keep complexity low. + +In the future it could be possible to extend ESO to have a state and accept transactions from a system address to store the passed data -- similarly to what [EIP-210] proposed. + +Proposals wanting to introduce more data to the state, which is not part of blocks or transactions, should aim to extend the ESO. + +At this time it is not proposed to make the ESO into a contract existing in the state, but to include it as a precompile and leave the implementation details to the client. +In the future if it is sufficiently extended and a need arises to have a state, it would make sense to move it from being a precompile and have actual code. + +### Chain identifier + +Initially, a feature to read the current chain identifier is introduced: `getCurrentChainId()` returns the current chain identifier as a `uint64` encoded value. +It should be a non-payable function, which means sending any value would revert the transaction as described in [EIP-140]. +This has been proposed as [EIP-1344]. + +The contract ABI JSON is the following: +```json +[ + { + "constant": true, + "inputs": [], + "name": "getCurrentChainId", + "outputs": [ + { + "name": "", + "type": "uint64" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + } +] +``` + +This will be translated into sending the bytes `5cf0e8a4` to the ESO and returning the bytes `0000000000000000000000000000000000000000000000000000000000000001` for Ethereum mainnet. + +**Note:** It should be possible to introduce another interface checking the validity of a chain identifier in the chain history or for a given block (see [EIP-1959] and [EIP-1965]). + +## Rationale + + +## Backwards Compatibility + + +## Test Cases + + +## Implementation + + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[Contract ABI Encoding]: https://solidity.readthedocs.io/en/latest/abi-spec.html +[EIP-140]: https://eips.ethereum.org/EIPS/eip-140 +[EIP-210]: https://eips.ethereum.org/EIPS/eip-210 +[EIP-1344]: https://eips.ethereum.org/EIPS/eip-1344 +[EIP-1959]: https://github.com/ethereum/EIPs/pull/1959 +[EIP-1965]: https://github.com/ethereum/EIPs/pull/1965 diff --git a/EIPS/eip-2015.md b/EIPS/eip-2015.md new file mode 100644 index 0000000000000..f3f0a1878575d --- /dev/null +++ b/EIPS/eip-2015.md @@ -0,0 +1,81 @@ +--- +eip: 2015 +title: Wallet Update Chain JSON-RPC Method (`wallet_updateChain`) +author: Pedro Gomes (@pedrouid) +discussions-to: https://ethereum-magicians.org/t/eip-2015-wallet-update-chain-json-rpc-method-wallet-updatechain/3274 +status: Draft +type: Standards Track +category: ERC +created: 2019-05-12 +requires: 155, 1474 +--- + +## Simple Summary +Wallets can update the active chain when connected to a Dapp but not vice-versa, with `wallet_updateChain` the Dapp will be able to request this change from the Wallet. + +## Abstract +Dapp can request the Wallet to switch chains by providing the minimal parameters of `chainId`, `networkId`, `rpcUrl` and `nativeCurrency`. The Wallet will display a UI element to inform the user of this change. + +## Motivation +Wallet and Dapp communication rely on the present provider that acts as middleware between the two. Using JSON-RPC methods, the Dapp is able to access not only the active accounts but also the active chain. With [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102) we introduced the ability for Dapps to request access to the active accounts and the Wallet is able to provide a simple UI to inform the user of this action however the same is not currently possible for switching chains. The current pattern is to display some UI to request the user to switch chains within the Dapp, however this could be easily improved by triggering a UI from the Wallet side that can be approved or rejected by the user instead. + +## Specification +The JSON RPC method will be part of `wallet_` namespaced methods which aim to improve the UX and interoperability between Dapps and Wallets. + +### Required Parameters +- chainId (number): the id of the chain complaint with EIP-155 +- networkId (number): the id of the chain's network +- rpcUrl (string): the url endpoint for RPC requests for this chain +- nativeCurrency (Object): includes two fields for `name` (string) and `symbol` (string) + + +### Best Practices +- The Wallet should display a UI view similar to a [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102) informing the user that the currently connected Dapp wants to switch to the specified chain. +- the Wallet should default the rpcUrl to any existing endpoints matching a chainId known previously to the wallet, otherwise it will use the provided rpcUrl as a fallback. +- the Wallet should call the rpcUrl with `net_version` and `eth_chainId` to verify the provided chainId and networkId match the responses from the rpcUrl +- the Wallet should change all nativeCurrency symbols to the provided parameter + +### Example 1 +A JSON-RPC request from a Dapp to switch the Ethereum Goerli chain would be as follows: +```json +{ + "id":1, + "jsonrpc": "2.0", + "method": "wallet_updateChain", + "params": [ + { + "chainId": 5, + "networkId": 5, + "rpcUrl": "https://goerli.infura.io/v3/406405f9c65348f99d0d5c27104b2213", + "nativeCurrency": { + "name": "Goerli ETH", + "symbol": "gorETH" + } + } + ] +} +``` + +### Example 2 +A JSON-RPC request from a Dapp to switch the POA Network's xDAI chain would be as follows: +```json +{ + "id":1, + "jsonrpc": "2.0", + "method": "wallet_updateChain", + "params": [ + { + "chainId": 100, + "networkId": 100, + "rpcUrl": "https://dai.poa.network", + "nativeCurrency": { + "name": "xDAI", + "symbol": "xDAI" + } + } + ] +} +``` + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2025.md b/EIPS/eip-2025.md new file mode 100644 index 0000000000000..ea8e8be49959e --- /dev/null +++ b/EIPS/eip-2025.md @@ -0,0 +1,217 @@ +--- +eip: 2025 +title: Block Rewards Proposal for funding Eth1.x +author: James Hancock (@madeoftin) +discussions-to: https://github.com/MadeofTin/EIPs/issues +status: Draft +type: Standards Track +category: Core +created: 2019-04-20 +requires: 1890 +--- + +## Simple Summary + +Add `0.0055 ETH` per block for 18 months as a developer block reward reserved for funding Ethereum1.X development. + + +[EIP-1890](http://eips.ethereum.org/EIPS/eip-1890) proposes a mechanism to capture a portion of block rewards for sustainably funding ongoing network development. That EIP sets values and addresses to zero and so does not actually collect any rewards. This proposal is to explicitly set those values and begin collecting a portion of block rewards for 18 months in order to fund Ethereum 1.X working groups and organization efforts. This funding will be used to repay an initial loan provided by investors in the community funding this work with a small amount of interest. After 18 months the block reward would again reduce to zero. + + + +## Abstract + + +This EIP extends the mechanism established in EIP-1890 to add `0.044 ETH` to the block reward for a specific distribution period of `3,100,000 BLOCKS`(≈ 18 months). The `RECIPIENT_ADDRESS` is set to a smart contract with hardcoded denominations that distributes incoming ETH to a set of addresses for the purpose of Eth1.X development. The emission schedule would start at the hard fork block number and continue for `3,100,000 BLOCKS` (≈ 18 months) at which point the address and amount would again return to 0. Any further distribution would require a future hard fork. + +## Motivation + + +The context for this proposal came from attending the [Core Dev Eth1.X Meeting](https://www.youtube.com/watch?v=Au1Qll-86v0) in Berlin. Development is needed to move Eth1.X forward, and I observed that a lack of funding is the primary barrier to this work. This work can only be effectively conducted by working groups forming around these issues, and these working groups need funding in order to pay dedicated contractors and project managers. This proposal is a plan for funding these groups and supporting their operation. + +## Specification + + +Two constants will be introduced: + +- `REWARD_DURATION_IN_BLOCKS`, which specifies the number of blocks after `ISTANBUL_BLOCK_HEIGHT` when the reward collection will terminate (i.e., at block `ISTANBUL_BLOCK_HEIGHT + REWARD_DURATION_IN_BLOCKS`) +- `BENEFICIARY_ADDRESSES`, a list of tuples containing the address and the amount to be transferred to this address per block. These amounts will be determined as the loan is collected from participating organizations and the addresses for repayment will be specified by them. The total of the amounts will sum to 0.044. At the end of `REWARD_DURATION_IN_BLOCKS` the loan will be completely repaid. + +``` + +REWARD_DURATION_IN_BLOCKS = 3100000 +DEVFUND_BLOCK_REWARD = 0.044 + + + +BENEFICIARY_ADDRESSES = [ + (
, ), + (
, ) +] +``` + +Beginning with block `ISTANBUL_BLOCK_HEIGHT`, the reward is added to the participating addresses within `BENEFICIARY_ADDRESSES` at each block until the end of the `REWARD_DURATION_IN_BLOCKS`. + +``` +IF (CURRENT_BLOCK - ISTANBUL_BLOCK_HEIGHT <= REWARD_DURATION_IN_BLOCKS) + +FOR BENEFICIARY in BENEFICIARY_ADDRESSES: + BENEFICIARY[0].balance += BENEFICIARY[1] + +``` + +## Rewards Distribution Rationale +``` + Development loan repayment: 0.005 ETH per block: 15500 ETH total + Development loan interest (10% total over the period, simple interest): 0.0005 ETH per block: 1550 ETH total + + Total Block Reward Increase = `0.0055` ETH per block: 17050 ETH Total +``` + +*With a price of Etheruem at $150.00 this will raise approx USD $2,325,000.00 for developing Eth1.X over the next 18 months.* + + +![Block Rewards Distribution](https://docs.google.com/drawings/d/e/2PACX-1vRzpcFXvkftqEduftfCnNeJmjxQAyBjD1RMkuFt0JeURxSZ2oUSGA1HQ1-v5rjGeim2cn8IwF4UFH18/pub?w=873 "Logo Title Text 1") *Specific Addresses to be determined + +* [FAQ - Why hardcoded values?]( #why-hardcoded-values ) + + +## Rationale + + +There has been great public debate concerning EIP-1890, and one of the primary concerns is that it is difficult to evaluate the proposal without more complete information on how funds would be raised, how they would be administered, and how they would be used. There is a need for funding Eth1.x development and it is currently unclear where those funds will come from. This proposal is intended to give a more comprehensive proposal for its funding. In the case that ETH1.x is fully funded before the Istanbul upgrade I will withdraw this EIP. Until that point I intend to continue championing this proposal as a valid funding mechanism for this work. + +### Why a loan? + +The Eth1x initiative needs funding now, not in 18 months. A loan is necessary to complete certain stages of work before the funding mechanism begins to provide funds. A loan would provide this necessary funding today, and the investors willing to front this cost can recoup their contribution + a reward of *a fixed interest rate* for the risk on their loan. This arrangement will make it easier to find investors willing to participate who have sufficient funds. + +### Loan Repayment + +![Loan State Diagram](https://docs.google.com/drawings/d/e/2PACX-1vQrYtGONSu16KncNOjDJrtrbAfBRU1FAgl_2neZjkLiJVxJATAVPiEjKUfVElA9zU7pc-3cCizRgqFn/pub?h=400) + +There is a risk that the investors lose part of their contribution in the case that this EIP is rejected by the community between the time the funds have been collected and the beginning of the payout schedule. In this case all remaining funds will be returned to the contributors. The interest on the loan is an incentive for investors to participate in spite of this risk. Their downside is limited to the amount of funds spent before this EIP is accepted or rejected, which should be no more than about 5%, while their upside consists of the 10% simple interest paid over the period. + +### Development Loan + + +`Development Loan: 0.005` over 3.1 Million blocks = 15500 ETH + +**Funding Working Groups on 1.X** +* Funding Contractors, Coordinators, and project managers +* Working Groups defined with clear mandates + +Budget + +Working groups + - State rent (750k) + - Better sync (360k) + - finality gadget (360k) + - Fee market (360k) + - testing infrastructure (360k) + + +**ETH1.X Core Dev Gatherings** + +Funding hosting, traveling, and accommodations for necessary in-person gatherings of ETH1.X core developers similar to the Stanford and Berlin ETH1.X Core Dev Meeting held earlier this year. + +At the end of the 18 Months, the whole process would be torn down to prevent any internal tyranny of structurelessness forming within. + + + +* [FAQ - How will the funding of the devs be organized?]( #how-will-funding-the-devs-be-organized) + +## Accountability + +The funds will be transferred into DAI and secured in a multi-sig comprised of members of the community. Representatives from the following groups will receive a key. + + + - EIP Editors + - Geth + - Parity + - ConsenSys/PegaSys (PegaSys) + - The Ethereum Foundation (Hudson Jameson) + - Community + +## Personal Notes and Disclosure +I want to address any concerns about conflicts of interests directly. My participation with Eth1.X currently has been as a volunteer. I am in talks about a possible funded role helping with testing and coordination. If my work for with Eth1.x is funded, I will accept no additional funding collected by the mechanism proposed in this EIP. + +Eth1.X is the now of Ethereum and I would like to see it succeed. This is the intent of my proposal. + +### COI + +Previously I was PM for Tennagraph, a signalling solution for Ethereum. An Aragon grant funded this project and was distributed through Giveth and an AragonDAO. I have not received any funding from the project beyond this grant. All of this is verifiable on-chain. I am stepping down from any paid role on the project to continue as an advisor. I am also stepping down as a moderator for stances as there is a COI moderating stances for EIPs I am working with directly. + +### Disclaimer + +I do not claim to represent the community with my views; any members who wish to join supporting me with this proposal are free to do so. This is as fair of a proposal as I can personally conceive. + +## Backwards Compatibility + +This EIP has no impact on backwards compatibility. + +## Test Cases + +Not Implemented + +## Implementation + + +Not Implemented + +## FAQ + +### Why Hardcoded Values? + +Why not us a smart contract with some governance mechanism to allow changing the distribution of funds? Wouldn’t that be more flexible and effective? + +*TLDR: This EIP is not about governance reform* + +First, the payment of the loan will be hardcoded. Once agreed, the terms must be kept to give the lenders confidence in the repayment of the loan. As long as blocks are created the debt will be paid back. This is the essence of a trustless smart contract. + +After the loan, there is the option to allow the amounts (limited to less than .05ETH), and the locations (orgs that receive ecosystem funding) to be changed throughout the emission schedule. It is pretty easy to imagine a smart contract or DAO fulfilling this role. However, there are three classes of options available today we can consider when governing changes. + +* **Give the Keys to the Hands of the Few (Oligarchy)** + +Create a multisig that allows a group of individuals to update the smart contract. The most likely candidates for this are the Core Devs themselves, but it could also be a trusted few from the community/stakeholders. No matter how you slice it, there is a fundamental issue in deciding who gets to decide. There currently is not a trusted/adopted governance mechanism to make these decisions within the Ethereum ecosytem. Also, preventing changing the contract in self interest is difficult without a well-engineered governance system of checks and balances. This EIP does not claim nor aim to solve these issues. + +* **Give the Keys to the Hands of the Many (Plutarchy)** + +Allow ethereum holders with coin votes to update the smart contract. Using holographic consensus could overcome the issue of voter turnout as it scales as participation scales, even to the size of the whole network. This has some benefits as the entire network can participate. However, the problem is that some individuals in the network are over represented -- the wealthy. Without a solution to identity that has been agreed to and implemented by the entire Ethereum Network, there is no way around giving more power in votes to the rich. This EIP does not claim, nor aim to solve these issues. + +* **Use Ethereum Governance as it is Today** + +Criticisms or support aside, there is a system that governs Ethereum today. It is a mix of rough consensus among core devs, miners running nodes, clients implementing changes, and stakeholders adopting those changes. It includes yelling or not yelling on twitter and reddit. It is complicated and I don’t claim to understand it. Even without a clear view of how it works, there is evidence of its existence. This evidence is there are changes that have allowed to be implemented, and changes that have not allowed to be implemented in Ethereum. + +I do not aim to change Ethereum governance. Because this EIP has hardcoded values, it must go through the existing governance process, whatever that is, before it is implemented. It will then continue to operate until the end of the emission schedule. This is intentional. This makes it uncapturable. No party other then the ecosystem itself can modify the contract once it has been deployed. + +This EIP is not about governance reform. + +### Why not allow current client implementors fund this work? (EF, Consensys, Parity, etc...) + +Historically there has been a precedent that the Ethereum Foundation is solely responsible for funding the development of Ethereum. This process has evolved as the development has become more distributed. Aya Miyaguchi observed in a recent [Coindesk article](https://www.coindesk.com/ethereum-foundation-director-sets-new-vision-for-blockchain-non-profit), “it really is not only Ethereum Foundation people who are building [Ethereum]”. Yes, we could rely on the Ethereum Foundation to fund Eth1.X. But, why should we? This is a call for the network to come together and fund its own development. Ethereum _the network_ is not owned by any one organization or group of people. We are lucky to have the EF and I consider this EIP in support of their coordination efforts. + +### How Will Funding the Devs be Organized + +I do not profess to know the best way to organize these funds. There is work already in progress to organize these efforts championed by Alexey Akhunov. The following is a quote from a [recent medium article](https://medium.com/@akhounov/ethereum-1x-as-an-attempt-to-change-the-process-783efa23cf60): + +> “Going from funding a few implementation teams continuously and letting them do 'their stuff' to funding more specific and temporary initiatives requires looking at funding through different lenses. How much 'due diligence' and oversight is too much (in terms of overhead), who can decide whether working groups actually deliver, etc. This is also solvable, and also more on this will come later (not in this post)." + +My suggestion would be to create an Eth1.X core developer DAO using [DaoStack](https://daostack.io/) to coordinate membership and payment of the Core Devs, but ultimately they are capable of determining the system that works best for them. As long as the system is transparent and mature enough to distribute funds when the time comes, this is sufficient for now. + +### Isn't a loan considered a security, or is it? + +I am not a lawyer and will seek further guidance from lawyers in the field on this point in particular. From the research I have done and conversations I have had there is a very good argument that a loan of this nature will not be considered a security by the US Supreme Court. +As the result of [REVES ET AL. v . ERNST YOUNG 1990](https://casetext.com/case/reves-v-ernst-young), the court stated that a home loan, consumer financing, a loan secured by a lien on a small business or some assets of a small business, short term notes, or notes that formalize a debt incurred in the ordinary course of business are not securities. If the note resembles the items listed above (home loans, etc.) then the note will not be deemed a security. The Supreme Court provided four factors to determine if a note sufficiently resembles the types of notes that are not classified as securities. ([source](https://www.invigorlaw.com/loan-subject-securities-regulations/)) + +**Family Resemblance Test** + 1) The intentions of the company and the individual—if the company raised money for general use in a business enterprise, then the note is more likely to be a security; if the individual agreed to the loan primarily for the profit the note was expected to generate, the note is more likely to be a security. + 2) The plan of distribution—the more widely the note is offered, the more likely it is to be found a security. + 3) The expectations of the investing public—if the investors thought they were investing in a business to make a profit on their investment, the note is more likely to be found a security. + 4) Other risk-reducing factor—if the note is collateralized or otherwise less risky than common notes, the note is less likely to be found to be a security. + +The loan is for the specific use of supporting Eth1.X research and development. The distribution will not be widely offered and the note will be collateralized by the network itself, provided in ETH and repaid in ETH. In coordinating the collection of these funds recognise I may be legally liable for some of this work and I will do all of the due dilegence I can, seek legal counsel, and accept any legal repercussions resulting from this work. + +#### + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2026.md b/EIPS/eip-2026.md new file mode 100644 index 0000000000000..376c8c8da5795 --- /dev/null +++ b/EIPS/eip-2026.md @@ -0,0 +1,71 @@ +--- +eip: 2026 +title: State Rent H - Fixed Prepayment for accounts +author: Alexey Akhunov (@AlexeyAkhunov) +discussions-to: https://ethereum-magicians.org/t/eip-2026-fixed-rent-prepayment-for-all-accounts-change-h-from-state-rent-v3-proposal/3273 +status: Draft +type: Standards Track +category: Core +created: 2019-05-14 +--- + + + +## Simple Summary + +Creation of new accounts (both contracts and non-contracts) requires a fixed one-off rent prepayment. Pre-existed accounts require the same prepayment upon +the first modification. The act of rent prepayment causes the addition of an extra field to accounts, called `rentbalance`. This field becomes part of state. + +## Abstract + +This is part of the State Rent roadmap. This particular change introduces a fixed charge for state expansion that comes from adding new accounts to the state. Theoretically, it puts a bound on the number of accounts that can be ever created, because that fixed charge cannot be recycled via mining. + +## Motivation + +The penalty is levied to the transaction sender. Rather than raising the gas cost of account creation (that would direct levy towards the miner), this change directs prepayment into the account's special field, `rentbalance`. It addresses several shortcomings of the simple raising of the gas cost: +1. Prepayments cannot be recycled via mining, which puts a theoretical bound on number of accounts in the state (though it is unlikely to ever be reached). +2. It is not possible for miners to circumvent the penalty or to extend such circumventions onto other users (via private fee rebates, for example). +3. This prepayment will be used to cover state rent in the future, and it will allow newly created contracts with 0 endowment not to be evicted in the same block. +4. It makes is possible to refund `rentbalance` upon self-destruction - when contract is self-destructed, both `balance` and `rentbalance` are returned. +5. Prepayments on pre-existing accounts are necessary to prevent hoarding of accounts ahead of this change. + +## Specification + +On and after block `H`, every newly created account gets a new field `rentbalance` of type unsigned 256-bit integer. +On and after block `H`, any operation that leads to the creation of a new account, deducts the amount `ACCOUNT_PREPAYMENT` from `tx.origin`. This amount is added to the `rentbalance` field of the created account. +On and after block `H`, any operation that modifies an account that does not yet have `rentbalance` field, deducts the amount `ACCOUNT_PREPAYEMENT` from `tx.origin`. This amount is added to the `rentbalance` field of the modified account. This is a anti-hoarding measure. + +Operations leading to the creations of a new account: +1. Creation of a non-contract account by sending non-zero ETH to an address with no associated account +2. Creation of a non-contract account by the block with `coinbase` pointing to an address with no associated account +3. Creation of a non-contract account by `SELFDESTRUCT` with the argument being an address with no associated account +4. Creation of a contract by transaction without destination but with data. This can result in either converting a non-countract account into a contract account, or creation of a contract account. +5. Creation of a contract by execution of `CREATE` or `CREATE2`. This can result in either converting a non-countract account into a contract account, or creation of a contract account. + +After prepayments are introduced, there can be two reasons for ether to be deducted from `tx.origin`: purchasing and spending gas, and spending gas for prepayments. Gaslimit of a transaction currently plays a role of safety limit, where `gaslimit` * `gasprice` represents the maximum amount of wei the sender (`tx.origin`) authorises the transaction to deduct from its account. +After prepayments are introduced, `gaslimit` * `gasprice` will still represent the maximum amount of wei spend, but it will be used for both gas purchases and prepayments, as necessary. + +## Rationale + +Prior to rent prepayments, other alternatives were considered: +1. Simple raising of the gas cost - discussed in the Motivation section. +1. In [first version of State Rent proposal](https://github.com/ledgerwatch/eth_state/blob/master/State_rent.pdf), there was no notion of extra levy upon account creation. It created a slight usability issue, where newly created contracts with 0 endowment would be evicted in the same block (when rent is introduced). It delays the benefits of the State Rent programme until the actual introduction of rent (in second or third hard-fork). +2. In the [second version of State Rent proposal](https://github.com/ledgerwatch/eth_state/blob/master/State_Rent_2.pdf), there was a notion of lock-up. It is very similar to rent prepayment, with the different that lock-up would not be covering future rent payments. + +An alternative approach to limiting the prepayments (instead of the using `gaslimit` * `gasprice` as the limit) is to introduce a new dedicated field `prepaymenlimit` into the transaction. This field would only limit prepayments). Such approach would require changes in the transaction format, as well as changes in the user interface for transaction sender, and having two counters during the transaction execution - one for gas, and one for prepayments. + +## Backwards Compatibility + +This change is not backwards compatible and requires hard fork to be activated. +It might have some adverse effects on the existing contracts, due to more gas needed to be allocated for the creation of new accounts. These adverse effects need to analysed in more detail. + +## Test Cases + +Tests cases will be generated out of a reference implementation. + +## Implementation + +There will be proof of concept implementation to refine and clarify the specification. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2027.md b/EIPS/eip-2027.md new file mode 100644 index 0000000000000..eb7b4ced6bd71 --- /dev/null +++ b/EIPS/eip-2027.md @@ -0,0 +1,74 @@ +--- +eip: 2027 +title: State Rent C - Net contract size accounting +author: Alexey Akhunov (@AlexeyAkhunov) +discussions-to: https://ethereum-magicians.org/t/eip-2027-net-contract-size-accounting-change-c-from-state-rent-v3-proposal/3275 +status: Draft +type: Standards Track +category: Core +created: 2019-05-14 +--- + + + +## Simple Summary + +Ethereum starts counting the number of storage slots filled and emptied in the contracts. Since the number of pre-existing slots is not currently accounted +in the state, effectively, only net change in the number of slots is tracked. In the subsequent change, called *Gross contract size accounting*, the total +number of storage slots starts being tracked. + +## Abstract + +This is part of the State Rent roadmap. This particular change introduces initial, net accounting of the number of the contract storage slots. Though not very +useful on its own, it makes it possible to introduce gross accounting of the number of storage slots, which is useful for number of things: +1. Gas cost of operations suchs as `SLOAD` and `SSTORE` will need to be increased to compensate for extra bandwidth consumed by the block proofs. Although in +the beginning the cost would be fixed, it will later be automatically calibrated depending on the size of the contract `SLOAD` and `SSTORE` operate on. +2. Snapshot sync protocols, like *fast sync*, *warp sync*, *firehose*, *red queen*, and perhaps others, will benefit from having the correct size of the +contract storage present in the state (and therefore being provable via Merkle proofs). + +## Motivation + +Ethereum currently does not track the number of contract storage slots at all, and producing such number given the downloaded state cannot be done in +constant *O(1)* time. + +## Specification + +Each contract (account with `codeHash` field not equal to 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, which the hash of the empty code) gets a new uint64 field, called `storagesize`. On and after block `C`, the semantics of the operation `SSTORE` (`location`, `value`) changes as follows: +- If previous value of the [`location`] is 0, and value is not 0, *increment* `storagesize` (semantics of *increment* described below) +- If previous value of the [`location`] is not 0, and value is 0, *decrement* `storagesize` (semantics of *decrement* described below) +- As with other state changes, changes of `storagesize` get reverted when the execution frame reverts, i.e. it needs to use the same techniques as storage values, like journalling (in Geth), and substates (in Parity). +Value of `storagesize` is not observable from contracts at this point. + +### Semantics of *increment* `storagesize` +If `storagesize` is not present, `storagesize` = `HUGE_NUMBER` + 1. +If `storagesize` is present, `storagesize` = `storagesize` + 1. + +### Semantics of *decrement* `storagesize` +If `storagesize` is not present, `storagesize` = `HUGE_NUMBER` - 1. +If `storagesize` is present, `storagesize` = `storagesize` - 1. + +### Note of `HUGE_NUMBER` +There is a constant `HUGE_NUMBER`. It needs to be large enough so that no real metrics (contract storage size, number of accounts, number of contracts, total size of code, total size of storage) will never reach that number, and small enough that it fits in an unsigned 64-bit integer. +Current suggestion is to have `HUGE_NUMBER` = 2^63, which is binary representation is the a single bit in a 64-bit number. + +The idea is to make it decidable later whether the storagesize was ever incremented/decremented (presence of the field), and whether it has been converted from net to gross (by value being smaller than `HUGE_NUMBER/2` - because it will not be possible for any contract be larger than 2^62 at the block `C`). + +## Rationale + +A mechanism for estimation of contract storage size has been proposed [here](https://medium.com/@akhounov/estimation-approximate-of-the-size-of-contracst-in-ethereum-4642fe92d6fe). But it does have a big drawback of introducing a lot of complexity into the consensus +(in the form of estimation algorithm, which has quite a few edge cases to cater for different sizes of the storage). + +## Backwards Compatibility + +This change is not backwards compatible and requires hard fork to be activated. Since the newly introduced field is not observable, this change does not impact any operations of the existing smart contracts. + +## Test Cases + +Tests cases will be generated out of a reference implementation. + +## Implementation + +There will be proof of concept implementation to refine and clarify the specification. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2028.md b/EIPS/eip-2028.md new file mode 100644 index 0000000000000..e8b8230f7e72e --- /dev/null +++ b/EIPS/eip-2028.md @@ -0,0 +1,75 @@ +--- +eip: 2028 +title: Transaction data gas cost reduction +author: Alexey Akhunov (@AlexeyAkhunov), Eli Ben Sasson , Tom Brand , Louis Guthmann , Avihu Levy +discussions-to: https://ethereum-magicians.org/t/eip-2028-calldata-gas-cost-reduction/3280 +status: Draft +type: Standards Track +category: Core +created: 2019-05-03 +--- + +## Simple Summary +We propose to reduce the gas cost of Calldata (`GTXDATANONZERO`) from its current value of 68 gas per byte to a lower cost, to be backed by mathematical modeling and empirical estimates. The mathematical model is the one used in the works of Sompolinsky and Zohar [1] and Pass, Seeman and Shelat [2], which relates network security to network delay. We shall (1) evaluate the theoretical impact of lower Calldata gas cost on network delay using this model, (2) validate the model empirically, and (3) base the proposed gas cost on our findings. + +## Motivation +There are a couple of main benefits to accepting this proposal and lowering gas cost of Calldata +On-Chain Scalability: Generally speaking, higher bandwidth of Calldata improves scalability, as more data can fit within a single block. +* Layer two scalability: Layer two scaling solutions can improve scalability by moving storage and computation off-chain, but often introduce data transmission instead. + - Proof systems such as STARKs and SNARKs use a single proof that attests to the computational integrity of a large computation, say, one that processes a large batch of transactions. + - Some solutions use fraud proofs which requires a transmission of merkle proofs. + - Moreover, one optional data availability solution to layer two is to place data on the main chain, via Calldata. +* Stateless clients: The same model will be used to determine the price of the state access for the stateless client regime, which will be proposed in the State Rent (from version 4). There, it is expected that the gas cost of state accessing operation will increase roughly proportional to the extra bandwidth required to transmit the “block proofs” as well as extra processing required to verify those block proofs. + +## Specification +The gas per non-zero byte is reduced from 68 to TBD. Gas cost of zero bytes is unchanged. + +## Rationale +Roughly speaking, reducing the gas cost of Calldata leads to potentially larger blocks, which increases the network delay associated with data transmission over the network. This is only part of the full network delay, other factors are block processing time (and storage access, as part of it). Increasing network delay affects security by lowering the cost of attacking the network, because at any given point in time fewer nodes are updated on the latest state of the blockchain. + +Yonatan Sompolinsky and Aviv Zohar suggested in [1] an elegant model to relate network delay to network security, and this model is also used in the work of Rafael Pass, Lior Seeman and Abhi Shelat [2]. We briefly explain this model below, because we shall study it theoretically and validate it by empirical measurements to reach the suggested lower gas cost for Calldata. + +The model uses the following natural parameters: +* _lambda_ denotes the block creation rate [1/s]: We treat the process of finding a PoW +solution as a poisson process with rate _lambda_. +* _beta_ - chain growth rate [1/s]: the rate at which new blocks are added to +the heaviest chain. +* _D_ - block delay [s]: The time that elapses between the mining of a new block and its acceptance by all the miners (all miners switched to mining on top of that block). + +### _Beta_ Lower Bound +Notice that _lambda_ => _beta_, because not all blocks that are found will enter the main chain (as is the case with uncles). In [1] it was shown that for a blockchain using the longest chain rule, one may bound _beta_ from below by _lambda_/ (1+ D * _lambda_). This lower bound holds in the extremal case where the topology of the network is a clique in which the delay between each pair of nodes is D, the maximal possible delay. Recording both the lower and upper bounds on _beta_ we get + + _lambda_ >= _beta_ >= _lambda_ / (1 + D * _lambda_) (*) + +Notice, as a sanity check, that when there is no delay (D=0) then _beta_ equals _lambda_, as expected. + +### Security of the network +An attacker attempting to reorganize the main chain needs to generate blocks at a rate that is greater than _beta_. +Fixing the difficulty level of the PoW puzzle, the total hash rate in the system is correlated to _lambda_. Thus, _beta_ / _lambda_ is defined as the the *efficiency* of the system, as it measures the fraction of total hash power that is used to generate the main chain of the network. + +Rearranging (*) gives the following lower bound on efficiency in terms of delay: + + _beta_ / _lambda_ >= 1 / (1 + D * _lambda_) (**) + +### The _delay_ parameter D +The network delay depends on the location of the mining node within the network and on the current network topology (which changes dynamically), and consequently is somewhat difficult to measure directly. +Previously, Christian Decker and Roger Wattenhofer [3] showed that propagation time scales with blocksize, and Vitalik Buterin showed that uncle rate, which is tightly related to efficiency (**) measure, also scales with block size [4]. + +However, the delay function can be decomposed into two parts D = *D_t* + *D_p*, where _D_t_ is the delay caused by the transmission of the block and _D_p_ is the delay caused by the processing of the block by the node. Our model and tests will examine the effect of Calldata on each of _D_t_ and _D_p_, postulating that their effect is different. This may be particularly relevant for Layer 2 Scalability and for Stateless Clients (Rationales 2, 3 above) because most of the Calldata associated with these goals are Merkle authentication paths that have a large _D_t_ component but relatively small _D_p_ values. + +## Test Cases +To suggest the gas cost of calldata we shall conduct two types of tests: +1. Network tests, conducted on the Ethereum mainnet, used to estimate the effect on increasing block size on _D_p_ and _D_t_, on the overall network delay D and the efficiency ratio (**), as well as delays between different mining pools. Those tests will include regression tests on existing data, and stress tests to introduce extreme scenarios. +2. Local tests, conducted on a single node and measuring the processing time as a function of Calldata amount and general computation limits. + +## References +[1] Yonatan Sompolinsky, Aviv Zohar: [Secure High-Rate Transaction Processing in Bitcoin](https://eprint.iacr.org/2013/881.pdf). Financial Cryptography 2015: 507-527 + +[2] Rafael Pass, Lior Seeman, Abhi Shelat: [Analysis of the Blockchain Protocol in Asynchronous Networks](https://eprint.iacr.org/2016/454.pdf), ePrint report 2016/454 + +[3] Christian Decker, Roger Wattenhofer: [Information propagation in the Bitcoin network](http://www.gsd.inesc-id.pt/~ler/docencia/rcs1314/papers/P2P2013_041.pdf). P2P 2013: 1-10 + +[4] Vitalik Buterin: [Uncle Rate and Transaction Fee Analysis](https://blog.ethereum.org/2016/10/31/uncle-rate-transaction-fee-analysis/) + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2029.md b/EIPS/eip-2029.md new file mode 100644 index 0000000000000..5a2c49345efec --- /dev/null +++ b/EIPS/eip-2029.md @@ -0,0 +1,61 @@ +--- +eip: 2029 +title: State Rent A - State counters contract +author: Alexey Akhunov (@AlexeyAkhunov) +discussions-to: https://ethereum-magicians.org/t/eip-2029-state-counters-contract-change-a-from-state-rent-v3-proposal/3279 +status: Draft +type: Standards Track +category: Core +created: 2019-05-15 +--- + + + +## Simple Summary + +A smart contract is deployed on all Ethereum networks, at a pre-determined address, with the code that simply reads the slot in its storage specified by the +only parameter. Later, this contract becomes "special" in that Ethereum start writing state counters (number of total transactions, number of accounts, +etc.) into that contract. + +## Abstract + +This is part of the State Rent roadmap. This particular change introduces a place in the Ethereum state where various state counters can be stored. At this +point, the most important counter is the total number of transactions happened, and this counter will be used to populate the nonces of newly created +non-contract accounts. This way of populating nonce ensures replay protection for accounts that were evicted and then brought back by sending ether to them. + +## Motivation + +Ethereum currently does not have a special place in the state for tracking state counters such as number of transactions or number of accounts. + +## Specification + +Prior to the block A, a contract is deployed with the following code: +`0x60 0x20 0x60 0x00 0x80 0x80 0x35 0x54 0x90 0x52 0xF3`, which corresponds to this assembly: +`PUSH1 32 PUSH1 0 DUP1 DUP1 CALLDATALOAD SLOAD SWAP1 MSTORE RETURN` +Call to this contract accepts one 32-byte argument, `x`, and returns the value of the storage item [`x`]. + +This contract is deployed using `CREATE2` opcode in such a way that it has the same address on any network. + +## Rationale + +Two alternative solutions were considered so far: +1. Extending the structure of the Ethereum state to introduce more fields, and hence change the way the state root is constructed. The main downside of this +approach is the impact on the software what is currently coupled with the particular way the state root is constructed. Particularly it affects the software +that deals with merkle proofs derived from the state root. +2. Extended State Oracle ([EIP-2014](https://eips.ethereum.org/EIPS/eip-2014)). Under such proposal, there will be a precompile contract with standardised interface, capable of returning +current values of the counters. However, the actual data being returned by such oracle is not explicitly in the state, and is not Merkelised. It means that all the counters need to be added to the snapshots when the snapshot sync is perform, so they still present in the state, but implicitly. + +## Backwards Compatibility + +This change is backwards compatible and does not require hard fork to be activated. + +## Test Cases + +Tests cases will be created to ensure that the state counter contract returns its storage items correctly. + +## Implementation + +Implementation is envisaged as a transaction that can be posted from any Ethereum address and will cause the deployment of the state counter contract. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2031.md b/EIPS/eip-2031.md new file mode 100644 index 0000000000000..894eb0d9fc032 --- /dev/null +++ b/EIPS/eip-2031.md @@ -0,0 +1,61 @@ +--- +eip: 2031 +title: State Rent B - Net transaction counter +author: Alexey Akhunov (@AlexeyAkhunov) +discussions-to: https://ethereum-magicians.org/t/eip-2031-net-transaction-counter-change-b-from-state-rent-v3-proposal/3283 +status: Draft +type: Standards Track +category: Core +created: 2019-05-15 +requires: 2029 +--- + + + +## Simple Summary + +Ethereum starts to track the number of transactions inside its state (for now, only number of transactions after this change is introduced, therefore +it is called *Net* transaction count). +It is done by incrementing a storage slot in the special contract, called *State counter contract* ([EIP-2029](https://eips.ethereum.org/EIPS/eip-2029)). + +## Abstract + +It is part of the State Rent roadmap. This particular change makes any Ethereum transaction increment the transaction counter, which is a special storage slot +in the *State counter contract*. This counter will be used to populate the nonces of newly created +non-contract accounts. This way of populating nonce ensures replay protection for accounts that were evicted and then brought back by sending ether to them. + +## Motivation + +Ethereum currently does not have a special place in the state for tracking number of transactions. + +## Specification + +A new field, with the location 0 (that means it resides in the storage slot 0 in the state counter contract, and can +be read by calling that contract with argument being 32 zero bytes), is added to the state counter contract. It will eventually contain `txCount`, the total number of transactions processed up until that point. +On an after block B, or after the deployment of the state counter contract (which comes first), the field `txCount` is incremented after each transaction. Updating `txCount` means updating the storage of state counter contract at the location 0. These changes are never reverted. + +## Rationale + +Two main alternatives were proposed for the replay protection of the accounts that were evicted by subsequently brought back by sending ether to them: +1. Temporal replay protection. The nonce of the new accounts (and those brought back) is still zero, but a new `valid-until` field is introduced, making +transactions invalid for inclusion after the time specified in this field. This, however, has unwanted side effected related to the fact that account +nonces are not only used for replay protection, but also for computing the addresses of the deployed contracts (except those created by `CREATE2`). +2. Setting nonce of new accounts (and those brought back) to something depending on the current block number. This approach requires coming up with +an arbitrary parameter, which is the maximum number of transaction in the block, so that the new nonces never clash with the existing nonces. +This is mostly a concern for private networks at the moment, because they will potentially have significantly more transactions in a block. + +## Backwards Compatibility + +This change is not backwards compatible and requires hard fork to be activated. + +## Test Cases + +Tests cases will be generated out of a reference implementation. + +## Implementation + +There will be proof of concept implementation to refine and clarify the specification. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + diff --git a/EIPS/eip-2035.md b/EIPS/eip-2035.md new file mode 100644 index 0000000000000..6b0eac7f5866a --- /dev/null +++ b/EIPS/eip-2035.md @@ -0,0 +1,81 @@ +--- +eip: 2035 +title: Stateless Clients - Repricing SLOAD and SSTORE to pay for block proofs +author: Alexey Akhunov (@AlexeyAkhunov) +discussions-to: https://ethereum-magicians.org/t/eip-2035-stateless-clients-repricing-sload-and-sstore-to-pay-for-block-proofs/3284 +status: Draft +type: Standards Track +category: Core +created: 2019-05-16 +--- + + + +## Simple Summary + +The gas cost of EVM opcodes `SLOAD` and `SSTORE` increases in order to accommodate extra bandwidth required to propagate block proof together with the block +headers and block bodies, as explained [here](https://medium.com/@akhounov/data-from-the-ethereum-stateless-prototype-8c69479c8abc). + +## Abstract + +It is part of the State Rent roadmap. This particular change prepares Ethereum for introduction of the block proofs (current understanding is that they +can be introuced without a hard fork). The introduction of the block proofs allows any Ethereum node that wishes to receive them, to process transactions +in the blocks without needing to access the Ethereum state. All necessary information for the execution (and the proof of validity) is continued in the +block proofs. In most Ethereum nodes, it will speed up the block processing and reduce the memory footprint of such processing. For mining nodes, however, +there will be more work to do to construct and transmit the block proofs. Therefore, the extra charge (payable to the miners) is introduced. In the first +phase, only contract storage will be covered by the block proofs. It means that the Ethereum nodes will still need access to the accounts in the state, +but block proofs will make it optional to have access to contract storage for executing transactions. Therefore, only `SSTORE` and `SLOAD` opcodes are +affected. + +## Motivation + +There is [empirical analysis](https://github.com/holiman/vmstats/blob/master/README.md) showing that `SLOAD` opcode is currently underpriced in terms +of execution latency it adds to the block processing. The hypothesis is that it is due to the latency of the database accesses. In the same +analysis, `SSTORE` is not considered, because its effect on the database accesses can be (and are in many implementations) delayed until the end of +the block. Stateless clients approach to the contract storage will largely negate that latency because no database accesses will be required. +Instead, bandwidth consumption goes up. There is emprical analysis (unpublished, but will be) suggesting that 1 uncached `SSTORE` or `SLOAD` adds +at most 1 kB to the block proofs. At the current cost of data transmission (68 gas per byte), this translates to the increase of gas cost of both +operations by 69k gas. However, in light of proposal in [EIP-2028](https://eips.ethereum.org/EIPS/eip-2028), the increase can be made much smaller. + +## Specification + +Not very formal at the moment, but will be formalised with more research and prototyping. Gas of operations `SLOAD` and `SSTORE` increases by `X` gas when the storage slots accessed (read by `SLOAD` or written by `SSTORE`) were not previously accessed (by another `SLOAD` or `SSTORE`) during the same transaction. + +Future variant (will be possible after the implementation of the *Gross contract size acccounting*) is researched, where the increase is varied +depending on the size of the contract storage, i.e. `SLOAD` and `SSTORE` for smaller contracts will be cheaper. + +## Rationale + +[EIP-1884](https://eips.ethereum.org/EIPS/eip-1884) seeks to increase the gas cost of `SLOAD` but using a different justification +(latency of the execution as described in the Motivation). This EIP is likely to increase the cost of `SLOAD` by a larger amount, therefore partially +(because EIP-1884 also proposed other increases) supersedes EIP-1884. + +[EIP-2028](https://eips.ethereum.org/EIPS/eip-2028) describes the model that can be used for deciding the gas cost of data transmission. It is relevant +because in the stateless client regime `SSTORE` and `SLOAD` operations add more data to be transmitted (as well as computation to verify the proofs). + +The main alternate design is the rent proportional to the size of the contract storage, which unfortunately introduces a serious griefing +vulnerability problem, and so far the solution seems to be in redesigning and rewriting smart contracts in a way, which makes them not vulnerable. +However, this approach is likely to be very expensive on the non-technical (ecosystem) level. + +## Backwards Compatibility + +This change is not backwards compatible and requires hard fork to be activated. +There might also be an adverse effect of this change on the already deployed contract. It is expected that after this EIP and +[EIP-2026](https://eips.ethereum.org/EIPS/eip-2026) (rent prepayment for accounts), the recommendation will be made to raise the gas limit. This can somewhat dampen the +adverse effect of EIP. The most problematic cases would be with the contracts that assume certain gas costs of `SLOAD` +and `SSTORE` and hard-code them in their internal gas computations. For others, the cost of interacting with the contract +storage will rise and may make some dApps based on such interactions, non-viable. This is a trade off to avoid even bigger +adverse effect of the rent proportional to the contract storage size. However, more research is needed to more fully +analyse the potentially impacted contracts. + +## Test Cases + +Tests cases will be generated out of a reference implementation. + +## Implementation + +There will be proof of concept implementation to refine and clarify the specification. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + diff --git a/EIPS/eip-2045.md b/EIPS/eip-2045.md new file mode 100644 index 0000000000000..9836b9dbbaa61 --- /dev/null +++ b/EIPS/eip-2045.md @@ -0,0 +1,121 @@ +--- +eip: 2045 +title: Particle gas costs for EVM opcodes +author: Casey Detrio (@cdetrio), Alex Beregszaszi (@axic) +discussions-to: https://ethereum-magicians.org/t/eip-2045-fractional-gas-costs/3311 +status: Draft +type: Standards Track +category: Core +created: 2019-05-17 +--- + +## Abstract +According to recent benchmarks, EVM opcodes for computation (`ADD`, `SUB`, `MUL`, etc.) are generally overpriced relative to opcodes for storage I/O (`SLOAD`, `SSTORE`, etc.). Currently the minimum gas cost is 1 (i.e. one unit of gas), and most computational opcodes have a cost near to 1 (e.g. 3, 5, or 8), so the range in possible cost reduction is limited. A new minimum unit of gas, called a "particle", which is a fraction of 1 gas, would expand the range of gas costs and thus enable reductions below the current minimum. + +## Motivation +The transaction capacity of an Ethereum block is determined by the gas cost of transactions relative to the block gas limit. One way to boost the transaction capacity is to raise the block gas limit. Unfortunately, raising the block gas limit would also increase the rate of state growth, unless the costs of state-expanding storage opcodes (`SSTORE`, `CREATE`, etc.) are simultaneously increased to the same proportion. Increasing the cost of storage opcodes may have adverse side effects, such as shifting the economic assumptions around gas fees of deployed contracts, or possibly breaking invariants in current contract executions (as mentioned in [EIP-2035](https://eips.ethereum.org/EIPS/eip-2035)[1](#eip2035), more research is needed on the potential effects of increasing the cost of storage opcodes). + +Another way to boost the transaction capacity of a block is to reduce the gas cost of transactions. Reducing the gas costs of computational opcodes while keeping the cost of storage opcodes the same, is effectively equivalent to raising the block gas limit and simultaneously increasing the cost of storage opcodes. However, reducing the cost of computational opcodes might avoid the adverse side effects of an increase in cost of storage opcodes (again, more research is needed on this topic). + +Currently, computational opcode costs are already too close to the minimum unit of 1 gas to achieve the large degree of cost reductions that recent benchmarks[2](#evmbenchmarks) indicate would be needed to tune opcode gas costs to the performance of optimized EVM implementations. A smaller minimum unit called a "particle", which is a fraction (or subdivision) of 1 gas, would enable large cost reductions. + +## Specification +A new gas counter `particlesUsed` is added to the EVM, in addition to the existing gas counter `gasUsed`. The unit 1 gas is equal to 10000 particles (`PARTICLES_PER_GAS`). The `particlesUsed` counter is only increased for opcodes priced in particles (i.e. opcodes that cost less than 1 gas). If increasing `particlesUsed` results in an excess of 1 gas, then 1 gas is added to `gasUsed` (and deducted from `particlesUsed`). + +Where the current gas logic looks like this: +``` +def vm_execute(ext, msg, code): + # Initialize stack, memory, program counter, etc + compustate = Compustate(gas=msg.gas) + codelen = len(code) + + while compustate.pc < codelen: + opcode = code[compustate.pc] + compustate.pc += 1 + + compustate.gasUsed += opcode.gas_fee + + # out of gas error + if compustate.gasUsed > compustate.gasLimit: + return vm_exception('OUT OF GAS') + + if op == 'STOP': + return peaceful_exit() + elif op == 'ADD': + stk.append(stk.pop() + stk.pop()) + elif op == 'SUB': + stk.append(stk.pop() - stk.pop()) + elif op == 'MUL': + stk.append(stk.pop() * stk.pop()) + +..... +``` + +The new gas logic using particles might look like this: +``` +PARTICLES_PER_GAS = 10000 + +def vm_execute(ext, msg, code): + # Initialize stack, memory, program counter, etc + compustate = Compustate(gas=msg.gas) + codelen = len(code) + + while compustate.pc < codelen: + opcode = code[compustate.pc] + compustate.pc += 1 + + if opcode.gas_fee: + compustate.gasUsed += opcode.gas_fee + elif opcode.particle_fee: + compustate.particlesUsed += opcode.particle_fee + if compustate.particlesUsed >= PARTICLES_PER_GAS: + # particlesUsed will be between 1 and 2 gas (over 10000 but under 20000) + compustate.gasUsed += 1 + # remainder stays in particle counter + compustate.particlesUsed = compustate.particlesUsed % PARTICLES_PER_GAS + + # out of gas error + if compustate.gasUsed > compustate.gasLimit: + return vm_exception('OUT OF GAS') + + if op == 'STOP': + return peaceful_exit() + elif op == 'ADD': + stk.append(stk.pop() + stk.pop()) + elif op == 'SUB': + stk.append(stk.pop() - stk.pop()) + elif op == 'MUL': + stk.append(stk.pop() * stk.pop()) + +..... +``` + +The above pseudocode is written for clarity. A more performant implementation might instead keep a single `particlesUsed` counter by multiplying opcode gas costs by 10000 and the `gasLimit` by 10000, and convert particles back to gas with `ceil(particlesUsed / PARTICLES_PER_GAS)` at the end of execution. It may also be more performant to use a `PARTICLES_PER_GAS` ratio that is a power of 2 (such as 8192 or 16384) instead of 10000; the spec above is a draft and updates in response to feedback are expected. + +#### Opcode cost changes +Many computational opcodes will undergo a cost reduction, with new costs suggested by benchmark analyses. For example, the cost of `DUP` and `SWAP` are reduced from 3 gas to 3000 particles (i.e. 0.3 gas). The cost of `ADD` and `SUB` are reduced from 3 gas to 6000 particles. The cost of `MUL` is reduced from 5 gas to 5000 particles (i.e. 0.5 gas). + +## Rationale +Adoption of fractional gas costs should only be an implementation detail inside the EVM, and not alter the current user experience around transaction gas limits and block gas limits. The concept of `particles` need not be exposed to Ethereum users nor most contract authors, but only to EVM implementers and contract developers concerned with optimized gas usage. Furthermore, only the EVM logic for charging gas per opcode executed should be affected by this change. All other contexts dealing with gas and gas limits, such as block headers and transaction formats, should be unaffected. + +### Ewasm +The term "particles" was first introduced for Ewasm[3](#particle) to enable gas accounting for low cost wasm instructions, while remaining compatible with EVM gas costs. This EIP proposes introducing particles as a new minimum gas unit for EVM opcodes, and is not related to Ewasm. + +## Backwards Compatibility +This change is not backwards compatible and requires a hard fork to be activated. + +## Test Cases +TODO + +## Implementation +TODO + +## References +1. [EIP-2035](https://eips.ethereum.org/EIPS/eip-2035): Stateless Clients - Repricing SLOAD and SSTORE to pay for block proofs + +2. https://github.com/ewasm/benchmarking + +3. The term "particle" was inspired by a proposal for [Ewasm gas costs](https://github.com/ewasm/design/blob/e77d8e3de42784f40a803a23f58ef06881142d9f/determining_wasm_gas_costs.md). + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2046.md b/EIPS/eip-2046.md new file mode 100644 index 0000000000000..ca35c7eefe8e8 --- /dev/null +++ b/EIPS/eip-2046.md @@ -0,0 +1,69 @@ +--- +eip: 2046 +title: Reduced gas cost for static calls made to precompiles +author: Alex Beregszaszi (@axic) +discussions-to: https://ethereum-magicians.org/t/eip-2046-reduced-gas-cost-for-static-calls-made-to-precompiles/3291 +status: Draft +type: Standards Track +category: Core +created: 2019-05-17 +requires: 214, 1352 +--- + +## Simple Summary + +This change reduces the gas cost of using precompiled contracts. + +## Abstract + +Reduce the base gas cost of calling precompiles using `STATICCALL` from 700 to 40. This should allow more efficient use of precompiles as well as precompiles with a total cost below 700. + +## Motivation + +The Spurious Dragon hard fork increased the cost of calls significantly to account for loading contract code from the state without making an exception for precompiles, whose "code" is always loaded. + +This made use of certain precompiles impractical. + +FIXME: extend this with recent reasoning about ECC repricings. + +## Specification + +After block `HF` the `STATICCALL` (`0xfa`) instruction charges different basic gas cost (Gcall in [Yellow Paper]'s notation) depending on the destination address provided: +- for precompiles (address range as per [EIP-1352]) the cost is `40` +- for every other address the cost remains unchanged (`700`) + +## Rationale + +Only the `STATICCALL` instruction was changed to reduce the impact of the change. This should not be a limiting factor, given precompiles (currently) do not have a state and cannot change the state. +However, contracts created and deployed before Byzantium likely will not use `STATICCALL` and as a result this change will not reduce their costs. + +Contrary to EIP-1109 gas reduction to `0` is not proposed. The cost `40` is kept as a cost representing the context switching needed. + +## Backwards Compatibility + +This EIP should be backwards compatible. The only effect is that the cost is reduced. Since the cost is not reduced to zero, it should not be possible for a malicious proxy contract, when deployed before +the `HF`, to do any state changing operation. + +## Test Cases + +TBA + +## Implementation + +TBA + +## References + +This has been previously suggested as part of [EIP-1109](https://github.com/ethereum/EIPs/pull/1109) and [EIP-1231](https://github.com/ethereum/EIPs/pull/1231). +However EIP-1109 was later changed to a very different approach. The author [has suggested to change EIP-1109](https://ethereum-magicians.org/t/eip-1109-remove-call-costs-for-precompiled-contracts/447/7). + +## Acknowledgements + +Jordi Baylina (@jbaylina) and Matthew Di Ferrante (@mattdf) who have proposed this before. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[Yellow Paper]: https://github.com/ethereum/yellowpaper +[EIP-1352]: https://eips.ethereum.org/EIPS/eip-1352 diff --git a/EIPS/eip-210.md b/EIPS/eip-210.md index 859991c1f026d..abba50af202e5 100644 --- a/EIPS/eip-210.md +++ b/EIPS/eip-210.md @@ -83,4 +83,4 @@ The EVM bytecode that the contract code should be set to is: ### Rationale -This removes the need for implementaitons to have an explicit way to look into historical block hashes, simplifying the protocol definition and removing a large component of the "implied state" (information that is technically state but is not part of the state tree) and thereby making the protocol more "pure". Additionally, it allows blocks to directly point to blocks far behind them, which enables extremely efficient and secure light client protocols. +This removes the need for implementations to have an explicit way to look into historical block hashes, simplifying the protocol definition and removing a large component of the "implied state" (information that is technically state but is not part of the state tree) and thereby making the protocol more "pure". Additionally, it allows blocks to directly point to blocks far behind them, which enables extremely efficient and secure light client protocols. diff --git a/EIPS/eip-2159.md b/EIPS/eip-2159.md new file mode 100644 index 0000000000000..115fa66c84522 --- /dev/null +++ b/EIPS/eip-2159.md @@ -0,0 +1,61 @@ +--- +eip: 2159 +title: Common Prometheus Metrics Names for Clients +author: Adrian Sutton (@ajsutton) +discussions-to: https://ethereum-magicians.org/t/common-chain-metrics/3415 +status: Draft +type: Standards Track +category: Interface +created: 2019-07-01 +--- + + + +## Simple Summary + +Standardized names for common metrics Ethereum clients to use with the [Prometheus](https://prometheus.io), a widely used monitoring and alerting solution. + +## Abstract + +Many Ethereum clients expose a range of metrics in a format compatible with Prometheus to allow operators to monitor the client's behaviour and performance and raise alerts if the chain isn't progressing or there are other indications of errors. +While the majority of these metrics are highly client-specific, reporting on internal implementation details of the client, some are applicable to all clients. +By standardizing the naming and format of these common metrics, operators are able to monitor the operation of multiple clients in a single dashboard or alerting configuration. + +## Motivation + +Using common names and meanings for metrics which apply to all clients allows node operators to monitor clusters of nodes using heterogeneous clients using a single dashboard and alerting configuration. +Currently there are no agreed names or meanings, leaving client developers to invent their own making it difficult to monitor a heterogeneous cluster. + +## Specification + +The table below defines metrics which may be captured by Ethereum clients which expose metrics to Prometheus. Clients may expose additional metrics however these should not use the `ethereum_` prefix. + +| Name | Metric type | Definition | JSON-RPC Equivalent | +|----------------------------------|-------------|-------------------------------------------------------------------|---------------------------------------------------------------------| +| ethereum_blockchain_height | Gauge | The current height of the canonical chain | `eth_blockNumber` | +| ethereum_best_known_block_number | Gauge | The estimated highest block available | `highestBlock` of `eth_syncing` or `eth_blockNumber` if not syncing | +| ethereum_peer_count | Gauge | The current number of peers connected | `net_peerCount` | +| ethereum_peer_limit | Gauge | The maximum number of peers this node allows to connect | No equivalent | + +Note that `ethereum_best_known_block_number` always has a value. When the `eth_syncing` JSON-RPC method would return `false`, the current chain height is used. + +## Rationale + +The defined metrics are independent of Ethereum client implementation but provide sufficient information to create an overview dashboard to support monitoring a group of Ethereum nodes. + +There is a similar, though more prescriptive, specification for [beacon chain client metrics](https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md). +The specific details of how to expose the metrics has been omitted as there is variance in existing implementations and standardising this does not provide any significant benefit. + +## Backwards Compatibility + +This is *not* a consensus affecting change. + +Clients may already be publishing these metrics using different names and changing to the new form may break existing alerts or dashboards. Clients that want to avoid this incompatibility can expose the metrics under both the old and new names. + + +## Implementation + +These metrics are currently captured by [Pantheon](https://pegasys.tech) under `pantheon_` prefixed names. It is planned that they will be renamed to match this EIP in the next release ([see PR](https://github.com/PegaSysEng/pantheon/pull/1634)). + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-225.md b/EIPS/eip-225.md index 2404a73bd4fa6..f224cb96c4976 100644 --- a/EIPS/eip-225.md +++ b/EIPS/eip-225.md @@ -3,7 +3,7 @@ eip: 225 title: Clique proof-of-authority consensus protocol author: Péter Szilágyi discussions-to: https://github.com/ethereum/EIPs/issues/225 -status: Draft +status: Final type: Standards Track category: Core created: 2017-03-06 diff --git a/EIPS/eip-233.md b/EIPS/eip-233.md index dd6877f29681c..a3378d67c30ef 100644 --- a/EIPS/eip-233.md +++ b/EIPS/eip-233.md @@ -18,13 +18,96 @@ Today discussions about hard forks happen at various forums and sometimes in ad- ## Specification -A Meta EIP should be created and merged as a *Draft* as soon as a new hard fork is planned. This EIP should contain: +A Meta EIP should be created and merged as a *Draft* as soon as a new hard fork is planned. + +This EIP should contain: - the desired codename of the hard fork, -- list of all the EIPs included in the hard fork and -- activation block number once decided and +- activation block number once decided +- a timeline section +- an EIPs to include section - the **Requires** header should point to the previous hard fork meta EIP. -The draft shall be updated with summaries of the decisions around the hard fork. It should move in to the `Accepted` state once the changes are frozen (i.e. all referenced EIPs are in the `Accepted` state) and in to the `Final` state once the hard fork has been activated. +The draft shall be updated with summaries of the decisions around the hard fork. + +### Timeline + +Once a timeline with key dates is agreed upon for other crucial dates. The basic outline of a hardfork timeline should include: +* Hard deadline to accept proposals for this hard fork +* Soft deadline for major client implementations +* Projected date for testnet network upgrade +* Projected date for mainnet upgrade (the activation block number / projected date for this block) + +### EIP Inclusion Process + +Anyone that wishes to propose a Core EIP for the hard fork should make a PR against the Meta EIP representing the hard fork. The EIP must be published as at least `Draft`. It enters the _Proposed EIPs_ section, along with at least one person who is a point of contact for wanting to include the EIP. + +EIPs can move states by discussion done on the "[All Core Devs Meetings](https://github.com/ethereum/pm/)": +- If accepted for a hard fork, the EIP should be moved to the _Accepted EIPs_ section. If the EIP has major client implementations and no security issues by the timeline date, it is scheduled for inclusion. +- If rejected from a hard fork, the EIP should be moved to the _Rejected EIPs_ section. +- Once the EIPs in the _Accepted EIPs_ section have successfully launched on a testnet roll out, they are moved to the _Included EIPs_ section. + +--- + +The Meta EIP representing the hard fork should move in to the `Accepted` state once the changes are frozen (i.e. all referenced EIPs are in the `Accepted` state) and in to the `Final` state once the hard fork has been activated. + +## Template + +A template for the [Istanbul Hardfork Meta 1679](https://eips.ethereum.org/EIPS/eip-1679) is included below ([source file on Github](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1679.md)): + +``` +{% raw %} +--- +eip: 1679 +title: "Hardfork Meta: Istanbul" +author: Alex Beregszaszi (@axic), Afri Schoedon (@5chdn) +type: Meta +status: Draft +created: 2019-01-04 +requires: 1716 +--- + +## Abstract + +This meta-EIP specifies the changes included in the Ethereum hardfork named Istanbul. + +## Specification + +- Codename: Istanbul +- Activation: TBD + +### Included EIPs + +- TBD + +### Accepted EIPs + +- TBD + +### Rejected EIPs + +- TBD + +### Proposed EIPs + +- TBD + +## Timeline + +* 2019-05-17 (Fri) hard deadline to accept proposals for "Istanbul" +* 2019-07-19 (Fri) soft deadline for major client implementations +* 2019-08-14 (Wed) projected date for testnet network upgrade (Ropsten, Görli, or ad-hoc testnet) +* 2019-10-16 (Wed) projected date for mainnet upgrade ("Istanbul") + +## References + +- TBD (e.g. link to Core Dev notes or other references) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +{% endraw %} +``` ## Rationale diff --git a/EIPS/eip-234.md b/EIPS/eip-234.md index 06f99c5e59ffc..1398c161b9b6f 100644 --- a/EIPS/eip-234.md +++ b/EIPS/eip-234.md @@ -6,6 +6,7 @@ type: Standards Track category: Interface status: Draft created: 2017-03-24 +requires: 1474 --- ## Simple Summary diff --git a/EIPS/eip-3.md b/EIPS/eip-3.md index 6337851663540..621b143554d6b 100644 --- a/EIPS/eip-3.md +++ b/EIPS/eip-3.md @@ -16,11 +16,11 @@ This is a proposal to add a new opcode, `CALLDEPTH`. The `CALLDEPTH` opcode woul There is a limit specifying how deep contracts can call other contracts; the call stack. The limit is currently `256`. If a contract invokes another contract (either via `CALL` or `CALLCODE`), the operation will fail if the call stack depth limit has been reached. -This behaviour makes it possible to subject a contract to a "call stack attack" [1]. In such an attack, an attacker first creates a suitable depth of the stack, e.g. by recursive calls. After this step, the attacker invokes the targeted contract. If the targeted calls another contract, that call will fail. If the return value is not properly checked to see if the call was successfull, the consequences could be damaging. +This behaviour makes it possible to subject a contract to a "call stack attack" [1]. In such an attack, an attacker first creates a suitable depth of the stack, e.g. by recursive calls. After this step, the attacker invokes the targeted contract. If the targeted calls another contract, that call will fail. If the return value is not properly checked to see if the call was successful, the consequences could be damaging. Example: -1. Contract `A` want's to be invoked regularly, and pays Ether to the invoker in every block. +1. Contract `A` wants to be invoked regularly, and pays Ether to the invoker in every block. 2. When contract `A` is invoked, it calls contracts `B` and `C`, which consumes a lot of gas. After invocation, contract `A` pays Ether to the caller. 3. Malicious user `X` ensures that the stack depth is shallow before invoking A. Both calls to `B` and `C` fail, but `X` can still collect the reward. diff --git a/EIPS/eip-4.md b/EIPS/eip-4.md index 7527271265a52..44966a8cdfd10 100644 --- a/EIPS/eip-4.md +++ b/EIPS/eip-4.md @@ -1,11 +1,11 @@ --- eip: 4 -layer: Process title: EIP Classification -author: Joseph Chow -status: Draft +author: Joseph Chow (@ethers) +status: Superseded type: Meta created: 2015-11-17 +superseded-by: 1 --- # Abstract diff --git a/EIPS/eip-5.md b/EIPS/eip-5.md index dfde87b3f110b..bb47fbe6d9300 100644 --- a/EIPS/eip-5.md +++ b/EIPS/eip-5.md @@ -108,7 +108,7 @@ The change in semantics affects existing contracts in two ways: all be written in a way, though, such that objects in memory are _relocatable_, i.e. their absolute position in memory and their relative position to other objects does not matter. This is of course not the case for arrays, but they - are allocated in a single allocation and not with an intermidiate `CALL`. + are allocated in a single allocation and not with an intermediate `CALL`. ### Implementation diff --git a/EIPS/eip-6.md b/EIPS/eip-6.md index ea1b1032d5946..3e097521d4d3f 100644 --- a/EIPS/eip-6.md +++ b/EIPS/eip-6.md @@ -5,7 +5,6 @@ author: Hudson Jameson status: Final type: Standards Track category: Interface -layer: Applications created: 2015-11-22 --- diff --git a/EIPS/eip-615.md b/EIPS/eip-615.md index 3db860cfbe3c6..d9d2b203f3ec7 100644 --- a/EIPS/eip-615.md +++ b/EIPS/eip-615.md @@ -69,9 +69,9 @@ Especially important is efficient translation to and from [eWasm](https://github These forms > *`INSTRUCTION`* > -> *`INSTRUCTION x`* +> *`INSTRUCTION x`* > -> *`INSTRUCTION x, y`* +> *`INSTRUCTION x, y`* name an *`INSTRUCTION`* with no, one and two arguments, respectively. An instruction is represented in the bytecode as a single-byte opcode. Any arguments are laid out as immediate data bytes following the opcode inline, interpreted as fixed length, MSB-first, two's-complement, two-byte positive integers. (Negative values are reserved for extensions.) @@ -102,7 +102,7 @@ To support subroutines, `BEGINSUB`, `JUMPSUB`, and `RETURNSUB` are provided. Br #### Switches, Callbacks, and Virtual Functions -Dynamic jumps are also used for `O(1)` indirection: an address to jump to is selected to push on the stack and be jumped to. So we also propose two more instructions to provide for constrained indirection. We support these with vectors of `JUMPDEST` or `BEGINSUB` offsets stored inline, which can be selected with an index on the stack. That constrains validation to a specified subset of all possible destinations. The danger of quadratic blow up is avoided because it takes as much space to store the jump vectors as it does to code the worst case exploit. +Dynamic jumps are also used for `O(1)` indirection: an address to jump to is selected to push on the stack and be jumped to. So we also propose two more instructions to provide for constrained indirection. We support these with vectors of `JUMPDEST` or `BEGINSUB` offsets stored inline, which can be selected with an index on the stack. That constrains validation to a specified subset of all possible destinations. The danger of quadratic blow up is avoided because it takes as much space to store the jump vectors as it does to code the worst case exploit. Dynamic jumps to a `JUMPDEST` are used to implement `O(1)` jumptables, which are useful for dense switch statements. Wasm and most CPUs provide similar instructions. @@ -193,7 +193,7 @@ frame | 21 ______|___________ 22 <- SP ``` -and after pushing two arguments and branching with `JUMPSUB` to a `BEGINSUB 2, 3` +and after pushing two arguments and branching with `JUMPSUB` to a `BEGINSUB 2, 3` ``` PUSH 10 PUSH 11 @@ -256,7 +256,7 @@ _Execution_ is as defined in the [Yellow Paper](https://ethereum.github.io/yello >**5** Invalid instruction -We propose to expand and extend the Yellow Paper conditions to handle the new instructions we propose. +We propose to expand and extend the Yellow Paper conditions to handle the new instructions we propose. To handle the return stack we expand the conditions on stack size: >**2a** The size of the data stack does not exceed 1024. @@ -290,7 +290,7 @@ All of the remaining conditions we validate statically. #### Costs & Codes -All of the instructions are `O(1)` with a small constant, requiring just a few machine operations each, whereas a `JUMP` or `JUMPI` must do an O(log n) binary search of an array of `JUMPDEST` offsets before every jump. With the cost of `JUMPI` being _high_ and the cost of `JUMP` being _mid_, we suggest the cost of `JUMPV` and `JUMPSUBV` should be _mid_, `JUMPSUB` and `JUMPIF` should be _low_, and`JUMPTO` and the rest should be _verylow_. Measurement will tell. +All of the instructions are `O(1)` with a small constant, requiring just a few machine operations each, whereas a `JUMP` or `JUMPI` must do an `O(log n)` binary search of an array of `JUMPDEST` offsets before every jump. With the cost of `JUMPI` being _high_ and the cost of `JUMP` being _mid_, we suggest the cost of `JUMPV` and `JUMPSUBV` should be _mid_, `JUMPSUB` and `JUMPIF` should be _low_, and`JUMPTO` and the rest should be _verylow_. Measurement will tell. We suggest the following opcodes: ``` @@ -315,7 +315,7 @@ These changes would need to be implemented in phases at decent intervals: If desired, the period of deprecation can be extended indefinitely by continuing to accept code not versioned as new—but without validation. That is, by delaying or canceling phase 2. -Regardless, we will need a versioning scheme like [EIP-1702](https://github.com/ethereum/EIPs/pull/1702) to allow current code and EIP-615 code to coexist on the same blockchain. +Regardless, we will need a versioning scheme like [EIP-1702](https://github.com/ethereum/EIPs/pull/1702) to allow current code and EIP-615 code to coexist on the same blockchain. ## Rationale @@ -325,7 +325,7 @@ As described above, the approach was simply to deprecate the problematic dynamic ## Implementation -Implementation of this proposal need not be difficult. At the least, interpreters can simply be extended with the new opcodes and run unchanged otherwise. The new opcodes require only stacks for the frame pointers and return offsets and the few pushes, pops, and assignments described above. The bulk of the effort is the validator, which in most languages can almost be transcribed from the pseudocode above. +Implementation of this proposal need not be difficult. At the least, interpreters can simply be extended with the new opcodes and run unchanged otherwise. The new opcodes require only stacks for the frame pointers and return offsets and the few pushes, pops, and assignments described above. The bulk of the effort is the validator, which in most languages can almost be transcribed from the pseudocode above. A lightly tested C++ reference implementation is available in [Greg Colvin's Aleth fork.](https://github.com/gcolvin/aleth/tree/master/libaleth-interpreter) This version required circa 110 lines of new interpreter code and a well-commented, 178-line validator. @@ -346,7 +346,7 @@ Validating that jumps are to valid addresses takes two sequential passes over th is_sub[code_size] // is there a BEGINSUB at PC? is_dest[code_size] // is there a JUMPDEST at PC? sub_for_pc[code_size] // which BEGINSUB is PC in? - + bool validate_jumps(PC) { current_sub = PC @@ -366,7 +366,7 @@ Validating that jumps are to valid addresses takes two sequential passes over th is_dest[PC] = true sub_for_pc[PC] = current_sub } - + // check that targets are in subroutine for (PC = 0; instruction = bytecode[PC]; PC = advance_pc(PC)) { @@ -390,7 +390,7 @@ Note that code like this is already run by EVMs to check dynamic jumps, includin #### Subroutine Validation -This function can be seen as a symbolic execution of a subroutine in the EVM code, where only the effect of the instructions on the state being validated is computed. Thus the structure of this function is very similar to an EVM interpreter. This function can also be seen as an acyclic traversal of the directed graph formed by taking instructions as vertexes and sequential and branching connections as edges, checking conditions along the way. The traversal is accomplished via recursion, and cycles are broken by returning when a vertex which has already been visited is reached. The time complexity of this traversal is `O(|E|+|V|): The sum of the number of edges and number of verticies in the graph. +This function can be seen as a symbolic execution of a subroutine in the EVM code, where only the effect of the instructions on the state being validated is computed. Thus the structure of this function is very similar to an EVM interpreter. This function can also be seen as an acyclic traversal of the directed graph formed by taking instructions as vertices and sequential and branching connections as edges, checking conditions along the way. The traversal is accomplished via recursion, and cycles are broken by returning when a vertex which has already been visited is reached. The time complexity of this traversal is `O(|E|+|V|)`: The sum of the number of edges and number of vertices in the graph. The basic approach is to call `validate_subroutine(i, 0, 0)`, for `i` equal to the first instruction in the EVM code through each `BEGINDATA` offset. `validate_subroutine()` traverses instructions sequentially, recursing when `JUMP` and `JUMPI` instructions are encountered. When a destination is reached that has been visited before it returns, thus breaking cycles. It returns true if the subroutine is valid, false otherwise. @@ -440,7 +440,7 @@ The basic approach is to call `validate_subroutine(i, 0, 0)`, for `i` equal to t return false if instruction is STOP, RETURN, or SUICIDE - return true + return true // violates single entry if instruction is BEGINSUB @@ -463,10 +463,10 @@ The basic approach is to call `validate_subroutine(i, 0, 0)`, for `i` equal to t if instruction is JUMPTO { PC = jump_target(PC) - continue + continue } - // recurse to jump to code to validate + // recurse to jump to code to validate if instruction is JUMPIF { if not validate_subroutine(jump_target(PC), return_pc, SP) diff --git a/EIPS/eip-627.md b/EIPS/eip-627.md index 0fe174eaf7584..00f0133baa569 100644 --- a/EIPS/eip-627.md +++ b/EIPS/eip-627.md @@ -66,7 +66,7 @@ This packet is used for sending the standard Whisper envelopes. This packet contains two objects: integer message code (0x02) followed by a single floating point value of PoW. This value is the IEEE 754 binary representation of 64-bit floating point number. Values of qNAN, sNAN, INF and -INF are not allowed. Negative values are also not allowed. -This packet is used by Whisper nodes for dynamic adjustment of their individual PoW requirements. Receipient of this message should no longer deliver the sender messages with PoW lower than specified in this message. +This packet is used by Whisper nodes for dynamic adjustment of their individual PoW requirements. Recipient of this message should no longer deliver the sender messages with PoW lower than specified in this message. PoW is defined as average number of iterations, required to find the current BestBit (the number of leading zero bits in the hash), divided by message size and TTL: @@ -165,7 +165,7 @@ Symmetric encryption uses AES GCM algorithm with random 96-bit nonce. Packet codes 0x00 and 0x01 are already used in all Whisper versions. -Packet code 0x02 will be necessary for the future developement of Whisper. It will provide possiblitity to adjust the PoW requirement in real time. It is better to allow the network to govern itself, rather than hardcode any specific value for minimal PoW requirement. +Packet code 0x02 will be necessary for the future development of Whisper. It will provide possiblitity to adjust the PoW requirement in real time. It is better to allow the network to govern itself, rather than hardcode any specific value for minimal PoW requirement. Packet code 0x03 will be necessary for scalability of the network. In case of too much traffic, the nodes will be able to request and receive only the messages they are interested in. diff --git a/EIPS/eip-663.md b/EIPS/eip-663.md index 47786a1d24a3a..eefa7f6f455cf 100644 --- a/EIPS/eip-663.md +++ b/EIPS/eip-663.md @@ -2,6 +2,7 @@ eip: 663 title: Unlimited SWAP and DUP instructions author: Alex Beregszaszi (@axic) +discussions-to: https://ethereum-magicians.org/t/eip-663-unlimited-swap-and-dup-instructions/3346 type: Standards Track category: Core status: Draft @@ -10,7 +11,7 @@ created: 2017-07-03 ## Abstract -`SWAP` and `DUP` instructions are limited to a stack depth of 16. Introduce two new instructions, `SWAPn` and `DUPn`, which lift this limitation and allow accessing the stack up to its full depth of 1024 items. +Currently, `SWAP` and `DUP` instructions are limited to a stack depth of 16. Introduce two new instructions, `SWAPn` and `DUPn`, which lift this limitation and allow accessing the stack up to its full depth of 1024 items. ## Motivation @@ -22,9 +23,12 @@ Introducing `SWAPn` and `DUPn` will provide an option to compilers to simplify a ## Specification +### Option A + Instructions `DUPn` (`0xb0`) and `SWAPn` (`0xb1`) are introduced, which take the top item from stack (referred to as `n`). If `n` exceeds 1024 or the current stack depth is less than `n`, then a stack underflow exception is issued. If the current stack depth is at the limit, a stack overflow exception is issued. +In both of these cases the EVM stops and all gas is consumed. Otherwise - for `DUPn` the stack item at depth `n` is duplicated at the top of the stack @@ -34,6 +38,20 @@ The gas cost for both instructions is set at 3. In reality the cost for such an Since both of these instructions require the top stack item to contain the position, it is still only possible to reach more than 16 stack items if there is at least one free stack slot. +This option has no effect no static analyzers, given no immediate value is introduced. + +### Option B + +The difference to Option A is that `DUPn` and `SWAPn` do not take the value of `n` from the top stack item, but instead encode it as a 16-bit big endian immediate value following the opcode. + +This results in wasting a byte in the cases of only referring to the top 255 stack items. + +### Option C + +This option extends Option B with two new instructions, `DUPSn` (`0xb2`) and `SWAPSn` (`0xb3`), where the value of `n` is encoded as an 8-bit immediate value following the opcode. + +The value `n` has a range of 0 to 255, but otherwise the same rules apply as in Option A. + ## Rationale TBA @@ -51,6 +69,12 @@ This has no effect on backwards compatibility. TBA +## References + +A similar proposal was made with [EIP-174](https://github.com/ethereum/EIPs/issues/174). Read the thread for some detailed discussion. + +Rootstock [RSKIP26](https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP26.md) also introduced `SWAPN` and `DUPN` with Option A described above. + ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-695.md b/EIPS/eip-695.md index 848d5335bf33b..0c58a05c19038 100644 --- a/EIPS/eip-695.md +++ b/EIPS/eip-695.md @@ -1,83 +1,84 @@ --- eip: 695 title: Create `eth_chainId` method for JSON-RPC -author: Isaac Ardis , Wei Tang , Fan Torchz (@tcz001) +author: Isaac Ardis , Wei Tang (@sorpaas), Fan Torchz (@tcz001) +discussions-to: https://ethereum-magicians.org/t/eip-695-create-eth-chainid-method-for-json-rpc/1845 type: Standards Track category: Interface -status: Draft +status: Last Call +review-period-end: 2019-07-20 created: 2017-08-21 +requires: 155, 1474 --- ## Simple Summary + Include `eth_chainId` method in `eth_`-namespaced JSON-RPC methods. ## Abstract + The `eth_chainId` method should return a single STRING result for an integer value in hexadecimal format, describing the -currently configured "Chain Id" value used for signing replay-protected transactions, +currently configured `CHAIN_ID` value used for signing replay-protected transactions, introduced via [EIP-155](./eip-155.md). ## Motivation -Currently although we can use net_version RPC call to get the + +Currently although we can use `net_version` RPC call to get the current network ID, there's no RPC for querying the chain ID. This makes it impossible to determine the current actual blockchain using the RPC. ## Specification ----- +### `eth_chainId` -### eth_chainId - -Returns the currently configured chain id, a value used in replay-protected transaction +Returns the currently configured chain ID, a value used in replay-protected transaction signing as introduced by [EIP-155](./eip-155.md). -##### Parameters -none +#### Parameters + +None. -##### Returns +#### Returns -`QUANTITY` - integer of the current chain id. Defaults are mainnet=61, morden=62. +`QUANTITY` - integer of the current chain ID. + +#### Example -##### Example ```js curl -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' // Result { - "id":83, + "id": 83, "jsonrpc": "2.0", "result": "0x3d" // 61 } ``` ----- - ## Rationale + An ETH/ETC client can accidentally connect to an ETC/ETH RPC endpoint without knowing it unless it tries to sign a transaction or it fetch a transaction that is known to have signed with a chain ID. This has since caused trouble for application developers, such as MetaMask, to add multi-chain support. -Please note related links: - -- [Parity PR](https://github.com/paritytech/parity/pull/6329) -- [Geth Classic PR (merged)](https://github.com/ethereumproject/go-ethereum/pull/336) - - ## Backwards Compatibility -Not relevant. -## Test Cases -Not currently implemented. +Not relevant. ## Implementation -Would be good to have a test to confirm that expected==got. + +- [Parity PR](https://github.com/paritytech/parity/pull/6329) +- [Geth PR](https://github.com/ethereum/go-ethereum/pull/17617) +- [Geth Classic PR](https://github.com/ethereumproject/go-ethereum/pull/336) ## Reference Return value `QUANTITY` adheres to standard JSON RPC hex value encoding, as documented here: https://github.com/ethereum/wiki/wiki/JSON-RPC#hex-value-encoding. ## Copyright + Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-706.md b/EIPS/eip-706.md index e1f601250f0ea..4211c23b75a42 100644 --- a/EIPS/eip-706.md +++ b/EIPS/eip-706.md @@ -16,7 +16,7 @@ This EIP proposes a tiny extension to the DEVp2p protocol to enable [Snappy comp ## Motivation Synchronizing the Ethereum main network (block 4,248,000) in Geth using fast sync currently consumes 1.01GB upload and 33.59GB download bandwidth. On the Rinkeby test network (block 852,000) it's 55.89MB upload and 2.51GB download. -However, most of this data (blocks, transactions) are heavily compressable. By enabling compression at the message payload level, we can reduce the previous numbers to 1.01GB upload / 13.46GB download on the main network, and 46.21MB upload / 463.65MB download on the test network. +However, most of this data (blocks, transactions) are heavily compressible. By enabling compression at the message payload level, we can reduce the previous numbers to 1.01GB upload / 13.46GB download on the main network, and 46.21MB upload / 463.65MB download on the test network. The motivation behind doing this at the DEVp2p level (opposed to eth for example) is that it would enable compression for all sub-protocols (eth, les, bzz) seamlessly, reducing any complexity those protocols might incur in trying to individually optimize for data traffic. @@ -46,7 +46,7 @@ Important caveats: ### Avoiding DOS attacks -Currently a DEVp2p message length is limited to 24 bits, amounting to a maximum size of 16MB. With the introduction of Snappy compression, care must be taken not to blindy decompress messages, since they may get significantly larger than 16MB. +Currently a DEVp2p message length is limited to 24 bits, amounting to a maximum size of 16MB. With the introduction of Snappy compression, care must be taken not to blindly decompress messages, since they may get significantly larger than 16MB. However, Snappy is capable of calculating the decompressed size of an input message without inflating it in memory (*[the stream starts with the uncompressed length up to a maximum of `2^32 - 1` stored as a little-endian varint](https://github.com/google/snappy/blob/master/format_description.txt#L20)*). This can be used to discard any messages which decompress above some threshold. **The proposal is to use the same limit (16MB) as the threshold for decompressed messages.** This retains the same guarantees that the current DEVp2p protocol does, so there won't be surprises in application level protocols. diff --git a/EIPS/eip-712.md b/EIPS/eip-712.md index f7e8f893fc12f..14fa4c37ad8e8 100644 --- a/EIPS/eip-712.md +++ b/EIPS/eip-712.md @@ -157,7 +157,7 @@ If the struct type references other struct types (and these in turn reference ev ### Definition of `encodeData` -The encoding of a struct instance is `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)`, i.e. the concatenation of the encoded member values in the order that they apear in the type. Each encoded member value is exactly 32-byte long. +The encoding of a struct instance is `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)`, i.e. the concatenation of the encoded member values in the order that they appear in the type. Each encoded member value is exactly 32-byte long. The atomic values are encoded as follows: Boolean `false` and `true` are encoded as `uint256` values `0` and `1` respectively. Addresses are encoded as `uint160`. Integer values are sign-extended to 256-bit and encoded in big endian order. `bytes1` to `bytes31` are arrays with a beginning (index `0`) and an end (index `length - 1`), they are zero-padded at the end to `bytes32` and encoded in beginning to end order. This corresponds to their encoding in ABI v1 and v2. @@ -205,7 +205,7 @@ By adding a prefix to the message makes the calculated signature recognisable as 1. `Address` - 20 Bytes - Address of the account that will sign the messages. 2. `TypedData` - Typed structured data to be signed. -Typed data is a JSON object containing type information, domain seprator parameters and the message object. Below is the [json-schema][jsons] definition for `TypedData` param. +Typed data is a JSON object containing type information, domain separator parameters and the message object. Below is the [json-schema][jsons] definition for `TypedData` param. [jsons]: https://json-schema.org/ diff --git a/EIPS/eip-725.md b/EIPS/eip-725.md index c69731a5b90b4..8688e9cc86975 100644 --- a/EIPS/eip-725.md +++ b/EIPS/eip-725.md @@ -19,7 +19,7 @@ The following describes standard functions for a unique identifiable proxy accou ## Motivation Standardizing a minimal interface for an proxy account allows third parties to interact with various proxy accounts contracts in a consistent manner. -the benefit is a persistent account that is independed from single keys and can attach an arbitrary amount of information to verifiy, or enhance the accounts purpose. +the benefit is a persistent account that is independent from single keys and can attach an arbitrary amount of information to verifiy, or enhance the accounts purpose. ## Specification diff --git a/EIPS/eip-747.md b/EIPS/eip-747.md new file mode 100644 index 0000000000000..01bd1233e43ac --- /dev/null +++ b/EIPS/eip-747.md @@ -0,0 +1,132 @@ +--- +eip: 747 +title: Add wallet_watchAsset to Provider +author: Dan Finlay (@danfinlay), Esteban Mino (@estebanmino) +discussions-to: https://ethereum-magicians.org/t/eip-747-eth-watchtoken/1048 +status: Draft +type: Standards Track +category: Interface +created: 2018-08-13 +requires: 1474 +--- + + + +## Simple Summary + +A method for allowing users to easily track new assets with a suggestion from sites they are visiting. + +## Abstract + +Web3 JavaScript wallet browsers may implement `wallet_watchAsset()` to allow any website to suggest a token for the user's wallet to track. + +## Motivation + +Today, one of the major uses of ethereum wallets is to acquire and track assets. Currently, each wallet either needs to pre-load a list of approved assets, or users need to be stepped through a tedious process of adding an asset for their given wallet. + +In the first case, wallets are burdened with both the security of managing this list, as well as the bandwidth of mass polling for known assets on their wallet. + +In the second case, the user experience is terrible. + +By leveraging a user's existing trust with websites they are learning about assets on, we are able to decentralize the responsibility of managing a user's list of known assets. + +## Specification + +A new method is added to web3 browsers' ethereum providers: + +```javascript + +/** +* @param {Object} opts - The options specifying the asset `type` and `options` specific for each of asset. +* @returns {Promise} success - Whether the user added the asset to their wallet. +*/ +async function wallet_watchAsset ( + opts +) { +/* Implementation would go here */ +} + +// Sample usage: +web3.wallet.watchAsset({ type, options }) +``` +As there are several types of different assets, this method has to provide support for each of them in a separate way. If it doesn't, it should give a response according to that. + +In the case of assets of type `ERC20`, this method works as follows. + +```javascript +web3.wallet.watchAsset({ + type: 'ERC20', + options: { address, symbol, decimals [, image] } +}) +``` + +The `image` parameter should link to a web-standard image format (png, jpg) of a reasonable size or a `Base64` image. To establish a baseline, let's say no greater than 512x512 pixels, and no greater than 256kb. However, this can be a client-defined setting. + +An example of use in the first case would be. + +```javascript +web3.wallet.watchAsset({ + type: 'ERC20', + options: { + address, + symbol, + decimals, + image: 'linktoimage.jpg' + } +}) +``` +Upon calling this request, the user should be prompted with the opportunity to add this token to their wallet: + +![add-token-prompt 1](../assets/eip-747/add-token-prompt.gif) + +For `Base64` images, the user just have to add it as `image` parameter. + +```javascript +const base64image = 'data:image/png;base64, ... ' +web3.wallet.watchAsset({ + type: 'ERC20', + options: { + address, + symbol, + decimals, + image: base64image + } +}) +``` +Upon calling this request, the user should be prompted with the opportunity to add this token to their wallet: + +![add-token-prompt 2](../assets/eip-747/add-token-prompt2.gif) + +If the user adds this token, it should appear somewhere in their wallet's UI, with its balance, etc. + +As a result of the addition or not of the asset a `Promise` should be returned, indicating if the user added the asset or an error if some parameter is not valid. + +In the case of an asset type that is not supported by the wallet, an error should appear indicating at least. + +``` +Asset of type (type) not supported +``` + +## Rationale + +Displaying a user's assets is a basic feature that every modern dapp user expects. However, keeping this list, and polling for it from the network can be costly, especially on bandwidth constrained devices. + +Most wallets today either manage their own assets list, which they store client side, or they query a centralized API for balances, which reduces decentralization, letting that API's owner easily correlate account holders with their IP addresses. + +Maintaining one of these assets lists becomes a political act, and maintainers can be subject to regular harassment and pressure to list otherwise unknown assets. + +Furthermore, automatically listing assets makes assets into a sort of spam mail: Users suddenly seeing new assets that they don't care about in their wallet can be used to bombard them with information that they didn't opt into. + +This phenomenon is exacerbated by the trend towards airdropped tokens, which has been a cause of network congestion, because spamming people with new tokens has so far been rewarded with user attention. + +While some people might suggest we begin a TCR of trusted tokens to watch, this would not solve the client-side bandwidth issues, nor the airdropped token spam issues. What we really want is a small list of tokens the user cares about. + +Most of the time a user is adding a asset, they learned about it on a website. At that moment, there is a natural alignment of interests, where the website wants the user to track their asset, and the user wants to track it. This is a natural point to introduce an API to easily allow these parties to collaborate, without involving the politics of the wallet's developers. + +## Implementation + +One implementation in progress can be viewed [on the MetaMask GitHub repository](https://github.com/MetaMask/metamask-extension/pull/4606). + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + diff --git a/EIPS/eip-758.md b/EIPS/eip-758.md index 8d7df949ce890..5cc85bb6f2a86 100644 --- a/EIPS/eip-758.md +++ b/EIPS/eip-758.md @@ -6,6 +6,7 @@ type: Standards Track category: Interface status: Draft created: 2017-11-09 +requires: 1474 --- ## Simple Summary @@ -46,7 +47,7 @@ Or to be notified of any transactions submitted by this rpc client when they com filter = {} ``` -After the request is recieved, the Ethereum node responds with a subscription ID: +After the request is received, the Ethereum node responds with a subscription ID: ```json {"jsonrpc": "2.0", "id": 1, "result": "0x00000000000000000000000000000b0b"} @@ -106,7 +107,7 @@ The node responds with an array of transaction hashes and their corresponding re } ``` -All transactions that were sealed _after_ the initial `eth_newCompletedTransactionFilter` request are included in this array. Again, if the `filter` param is a non-empty dictinary (contains either `from`, `to`, or `hasReturnData`) then only transactions matching the filter criteria generate notifications. Note that in the polling case, there is no way for the Ethereum node to be sure that an RPC client which submits a transaction was the same as the one who created the filter, so there is no restriction based on where the transaction was submitted. +All transactions that were sealed _after_ the initial `eth_newCompletedTransactionFilter` request are included in this array. Again, if the `filter` param is a non-empty dictionary (contains either `from`, `to`, or `hasReturnData`) then only transactions matching the filter criteria generate notifications. Note that in the polling case, there is no way for the Ethereum node to be sure that an RPC client which submits a transaction was the same as the one who created the filter, so there is no restriction based on where the transaction was submitted. ## Rationale diff --git a/EIPS/eip-777.md b/EIPS/eip-777.md index c4d54cdc01243..e57a19e655fc7 100644 --- a/EIPS/eip-777.md +++ b/EIPS/eip-777.md @@ -3,8 +3,7 @@ eip: 777 title: ERC777 Token Standard author: Jacques Dafflon , Jordi Baylina , Thomas Shababi discussions-to: https://github.com/ethereum/EIPs/issues/777 -status: Last Call -review-period-end: 2019-04-28 +status: Final type: Standards Track category: ERC created: 2017-11-20 @@ -67,7 +66,10 @@ interface ERC777Token { function granularity() external view returns (uint256); function defaultOperators() external view returns (address[] memory); - function isOperatorFor(address operator, address holder) external view returns (bool); + function isOperatorFor( + address operator, + address holder + ) external view returns (bool); function authorizeOperator(address operator) external; function revokeOperator(address operator) external; @@ -81,7 +83,12 @@ interface ERC777Token { ) external; function burn(uint256 amount, bytes calldata data) external; - function operatorBurn(address from, uint256 amount, bytes calldata data, bytes calldata operatorData) external; + function operatorBurn( + address from, + uint256 amount, + bytes calldata data, + bytes calldata operatorData + ) external; event Sent( address indexed operator, @@ -91,9 +98,24 @@ interface ERC777Token { bytes data, bytes operatorData ); - event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData); - event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); - event AuthorizedOperator(address indexed operator, address indexed holder); + event Minted( + address indexed operator, + address indexed to, + uint256 amount, + bytes data, + bytes operatorData + ); + event Burned( + address indexed operator, + address indexed from, + uint256 amount, + bytes data, + bytes operatorData + ); + event AuthorizedOperator( + address indexed operator, + address indexed holder + ); event RevokedOperator(address indexed operator, address indexed holder); } ``` @@ -101,9 +123,11 @@ The token contract MUST implement the above interface. The implementation MUST follow the specifications described below. The token contract MUST register the `ERC777Token` interface with its own address via [ERC1820]. -This is done by calling the `setInterfaceImplementer` function on the ERC1820 registry -with the token contract address as both the address and the implementer -and the `keccak256` hash of `ERC777Token` as the interface hash. + +> This is done by calling the `setInterfaceImplementer` function on the [ERC1820] registry +> with the token contract address as both the address and the implementer +> and the `keccak256` hash of `ERC777Token` (`0xac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce2177054`) +> as the interface hash. If the contract has a switch to enable or disable ERC777 functions, every time the switch is triggered, the token MUST register or unregister the `ERC777Token` interface for its own address accordingly via ERC1820. @@ -112,7 +136,7 @@ the `keccak256` hash of `ERC777Token` as the interface hash and `0x0` as the imp (See [Set An Interface For An Address][erc1820-set] in [ERC1820] for more details.) When interacting with the token contract, all amounts and balances MUST be unsigned integers. -I.e. Internally, all values are stored as a denomination of 1E-18 of a token. +I.e. internally, all values are stored as a denomination of 1E-18 of a token. The display denomination—to display any amount to the end user—MUST be 1018 of the internal denomination. @@ -204,7 +228,7 @@ The following rules MUST be applied regarding the *granularity*: - The *granularity* value MUST NOT be changed, ever. -- The *granularity* value MUST be greater or equal to `1`. +- The *granularity* value MUST be greater than or equal to `1`. - All balances MUST be a multiple of the granularity. @@ -214,7 +238,7 @@ The following rules MUST be applied regarding the *granularity*: - Any operation that would result in a balance that's not a multiple of the *granularity* value MUST be considered invalid, and the transaction MUST `revert`. -*NOTE*: Most of the tokens SHOULD be fully partition-able. +*NOTE*: Most tokens SHOULD be fully partition-able. I.e., this function SHOULD return `1` unless there is a good reason for not allowing any fraction of the token. > **identifier:** `556f0dc7` @@ -258,7 +282,7 @@ The rules below apply to *default operators*: - `AuthorizedOperator` events MUST NOT be emitted when defining *default operators*. -- A *holder* MUST be allowed revoke a *default operator* +- A *holder* MUST be allowed to revoke a *default operator* (unless the *holder* is the *default operator* in question). - A *holder* MUST be allowed to re-authorize a previously revoked *default operator*. @@ -371,7 +395,10 @@ as an *operator* for itself (i.e., if `operator` is equal to `msg.sender`). **`isOperatorFor` function** ``` solidity -function isOperatorFor(address operator, address holder) external view returns (bool) +function isOperatorFor( + address operator, + address holder +) external view returns (bool) ``` Indicate whether the `operator` address is an *operator* of the `holder` address. @@ -427,6 +454,10 @@ The token contract MUST `revert` when sending in any of the following cases: - Any of the resulting balances becomes negative, i.e. becomes less than zero (`0`). +- The `tokensToSend` hook of the *holder* `revert`s. + +- The `tokensReceived` hook of the *recipient* `revert`s. + The token contract MAY send tokens from many *holders*, to many *recipients*, or both. In this case: - The previous send rules MUST apply to all the *holders* and all the *recipients*. @@ -438,7 +469,7 @@ The token contract MAY send tokens from many *holders*, to many *recipients*, or *NOTE*: Mechanisms such as applying a fee on a send is considered as a send to multiple *recipients*: the intended *recipient* and the fee *recipient*. -*NOTE*: Transfer of tokens MAY be chained. +*NOTE*: Movements of tokens MAY be chained. For example, if a contract upon receiving tokens sends them further to another address. In this case, the previous send rules apply to each send, in order. @@ -468,7 +499,14 @@ In most of the cases the recipient would ignore the `operatorData`, or at most, **`Sent` event** ``` solidity -event Sent(address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData) +event Sent( + address indexed operator, + address indexed from, + address indexed to, + uint256 amount, + bytes data, + bytes operatorData +) ``` Indicate a send of `amount` of tokens from the `from` address to the `to` address by the `operator` address. @@ -505,7 +543,13 @@ The *operator* and the *holder* MUST both be the `msg.sender`. **`operatorSend` function** ``` solidity -function operatorSend(address from, address to, uint256 amount, bytes calldata data, bytes calldata operatorData) external +function operatorSend( + address from, + address to, + uint256 amount, + bytes calldata data, + bytes calldata operatorData +) external ``` Send the `amount` of tokens on behalf of the address `from` to the address `to`. @@ -536,7 +580,7 @@ as the minting process is generally specific for every token. Nonetheless, the rules below MUST be respected when minting for a *recipient*: -- Tokens MAY be minted for any *recipient* address. +- Tokens MAY be minted for any *recipient* address (except `0x0`). - The total supply MUST be increased by the amount of tokens minted. @@ -557,6 +601,7 @@ The token contract MUST `revert` when minting in any of the following cases: - The resulting *recipient* balance after the mint is not a multiple of the *granularity* defined by the token contract. - The *recipient* is a contract, and it does not implement the `ERC777TokensRecipient` interface via [ERC1820]. - The address of the *recipient* is `0x0`. +- The `tokensReceived` hook of the *recipient* `revert`s. *NOTE*: The initial token supply at the creation of the token contract MUST be considered as minting for the amount of the initial supply to the address(es) receiving the initial supply. @@ -588,7 +633,13 @@ The `tokensReceived()` hooks MAY use the information to decide if it wish to rej **`Minted` event** ``` solidity -event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData) +event Minted( + address indexed operator, + address indexed to, + uint256 amount, + bytes data, + bytes operatorData +) ``` Indicate the minting of `amount` of tokens to the `to` address by the `operator` address. @@ -612,7 +663,7 @@ The token contract MAY also define other functions to burn tokens. The rules below MUST be respected when burning the tokens of a *holder*: -- Tokens MAY be burned from any *holder* address. +- Tokens MAY be burned from any *holder* address (except `0x0`). - The total supply MUST be decreased by the amount of tokens burned. @@ -640,6 +691,8 @@ The token contract MUST `revert` when burning in any of the following cases: - The address of the *holder* is `0x0`. +- The `tokensToSend` hook of the *holder* `revert`s. + *[ERC20] compatibility requirement*: While a `Sent` event MUST NOT be emitted when burning; if the token contract is [ERC20] enabled, a `Transfer` event with the `to` parameter set to `0x0` SHOULD be emitted. @@ -664,7 +717,13 @@ MAY use the information to decide if they wish to reject the transaction. **`Burned` event** ``` solidity -event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); +event Burned( + ddress indexed operator, + address indexed from, + uint256 amount, + bytes data, + bytes operatorData +); ``` Indicate the burning of `amount` of tokens from the `from` address by the `operator` address. @@ -674,7 +733,7 @@ Indicate the burning of `amount` of tokens from the `from` address by the `opera > **parameters** > `operator`: Address which triggered the burn. > `from`: *Holder* whose tokens were burned. -> `amount`: Number of tokens burned. +> `amount`: Number of tokens burned. > `data`: Information provided by the *holder*. > `operatorData`: Information provided by the *operator*. @@ -693,13 +752,18 @@ The *operator* and the *holder* MUST both be the `msg.sender`. > **identifier:** `fe9d9303` > **parameters** -> `amount`: Number of tokens to burn. +> `amount`: Number of tokens to burn. > `data`: Information provided by the *holder*. **`operatorBurn` function** ``` solidity -function operatorBurn(address from, uint256 amount, bytes calldata data, bytes calldata operatorData) external +function operatorBurn( + address from, + uint256 amount, + bytes calldata data, + bytes calldata operatorData +) external ``` Burn the `amount` of tokens on behalf of the address `from`. @@ -729,6 +793,12 @@ The `tokensToSend` hook notifies of any request to decrement the balance (send a Any address (regular or contract) wishing to be notified of token debits from their address MAY register the address of a contract implementing the `ERC777TokensSender` interface described below via [ERC1820]. +> This is done by calling the `setInterfaceImplementer` function on the [ERC1820] registry +> with the *holder* address as the address, +> the `keccak256` hash of `ERC777TokensSender` +> (`0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895`) as the interface hash, +> and the address of the contract implementing the `ERC777TokensSender` as the implementer. + ``` solidity interface ERC777TokensSender { function tokensToSend( @@ -750,7 +820,14 @@ but said address MUST implement the interface on its behalf. **`tokensToSend`** ``` solidity -function tokensToSend(address operator, address from, address to, uint256 amount, bytes calldata userData, bytes calldata operatorData) external +function tokensToSend( + address operator, + address from, + address to, + uint256 amount, + bytes calldata userData, + bytes calldata operatorData +) external ``` Notify a request to send or burn (if `to` is `0x0`) an `amount` tokens from the `from` address to the `to` address @@ -769,26 +846,26 @@ by the `operator` address. The following rules apply when calling the `tokensToSend` hook: -- The `tokensToSend` hook MUST be called every time the balance is decremented. +- The `tokensToSend` hook MUST be called for every send and burn processes. - The `tokensToSend` hook MUST be called *before* the state is updated—i.e. *before* the balance is decremented. -- `operator` MUST be the address which triggered the decrease of the balance. +- `operator` MUST be the address which triggered the send or burn process. -- `from` MUST be the address of the *holder* whose balance is decreased. +- `from` MUST be the address of the *holder* whose tokens are sent or burned. -- `to` MUST be the address of the *recipient* whose balance is increased for a send. +- `to` MUST be the address of the *recipient* which receives the tokens for a send. - `to` MUST be `0x0` for a burn. -- `amount` MUST be the number of tokens the *holder* balance is decreased by. +- `amount` MUST be the number of tokens the *holder* sent or burned. -- `data` MUST contain the extra information provided by the *holder* (if any) for a send. +- `data` MUST contain the extra information (if any) provided to the send or the burn process. - `operatorData` MUST contain the extra information provided by the address which triggered the decrease of the balance (if any). -- The *holder* MAY block a decrease of its balance by `revert`ing. +- The *holder* MAY block a send or burn process by `revert`ing. (I.e., reject the withdrawal of tokens from its account.) *NOTE*: Multiple *holders* MAY use the same implementation of `ERC777TokensSender`. @@ -809,6 +886,12 @@ The `tokensReceived` hook notifies of any increment of the balance (send and min Any address (regular or contract) wishing to be notified of token credits to their address MAY register the address of a contract implementing the `ERC777TokensSender` interface described below via [ERC1820]. +> This is done by calling the `setInterfaceImplementer` function on the [ERC1820] registry +> with the *recipient* address as the address, +> the `keccak256` hash of `ERC777TokensRecipient` +> (`0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b`) as the interface hash, +> and the address of the contract implementing the `ERC777TokensRecipient` as the implementer. + ``` solidity interface ERC777TokensRecipient { function tokensReceived( @@ -838,7 +921,14 @@ but said address MUST implement the interface on its behalf. **`tokensReceived`** ``` solidity -function tokensReceived(address operator, address from, address to, uint256 amount, bytes calldata data, bytes calldata operatorData) external +function tokensReceived( + address operator, + address from, + address to, + uint256 amount, + bytes calldata data, + bytes calldata operatorData +) external ``` Notify a send or mint (if `from` is `0x0`) of `amount` tokens from the `from` address to the `to` address @@ -852,28 +942,32 @@ by the `operator` address. > `from`: *Holder* whose tokens were sent (or `0x0` for a mint). > `to`: Recipient of the tokens. > `amount`: Number of tokens the *recipient* balance is increased by. -> `data`: Information provided by the *holder*. +> `data`: Information provided by the *holder*. > `operatorData`: Information provided by the *operator*. The following rules apply when calling the `tokensReceived` hook: -- The `tokensReceived` hook MUST be called every time the balance is incremented. +- The `tokensReceived` hook MUST be called for every send and mint processes. - The `tokensReceived` hook MUST be called *after* the state is updated—i.e. *after* the balance is incremented. -- `operator` MUST be the address which triggered the increase of the balance. +- `operator` MUST be the address which triggered the send or mint process. -- `from` MUST be the address of the *holder* whose balance is decreased for a send. +- `from` MUST be the address of the *holder* whose tokens are sent for a send. - `from` MUST be `0x0` for a mint. -- `to` MUST be the address of the *recipient* whose balance is increased. +- `to` MUST be the address of the *recipient* which receives the tokens. + +- `amount` MUST be the number of tokens the *recipient* sent or minted. -- `amount` MUST be the number of tokens the *recipient* balance is increased by. +- `data` MUST contain the extra information (if any) provided to the send or the mint process. - `operatorData` MUST contain the extra information provided by the address which triggered the increase of the balance (if any). -- The *holder* MAY block an increase of its balance by `revert`ing. (I.e., reject the reception of tokens.) + +- The *holder* MAY block a send or mint process by `revert`ing. + (I.e., reject the reception of tokens.) *NOTE*: Multiple *holders* MAY use the same implementation of `ERC777TokensRecipient`. @@ -913,14 +1007,123 @@ If needed, other sizes MAY be created by converting from `SVG` into `PNG`. ## Rationale -This standard solves some of the shortcomings of [ERC20] while maintaining backward compatibility with [ERC20]. -It avoids the problems and vulnerabilities of [EIP223]. - -It goes a step further by allowing *operators* (generally contracts) -which can manage the tokens in the same way that the [ERC20] with infinite `approve` was allowed. -Finally, it adds hooks to provide further control to *holders* over their tokens. -Note that, the usage of [ERC1820] provides backward compatibility with wallets and existing contracts -without having to be redeployed thanks proxy contracts implementing the hooks. +The principal intent for this standard is +to solve some of the shortcomings of [ERC20] while maintaining backward compatibility with [ERC20], +and avoiding the problems and vulnerabilities of [EIP223]. + +Below are the rationales for the decisions regarding the main aspects of the standards. + +*NOTE*: Jacques Dafflon ([0xjac]), one of the authors of the standard, +conjointly wrote his [master thesis] on the standard, +which goes in more details than could reasonably fit directly within the standard, +and can provide further clarifications regarding certain aspects or decisions. + +### Lifecycle + +More than just sending tokens, [ERC777] defines the entire lifecycle of a token, +starting with the minting process, followed by the sending process and terminating with the burn process. + +Having a lifecycle clearly defined is important for consistency and accuracy, +especially when value is derived from scarcity. +In contrast when looking at some [ERC20] tokens, a discrepancy can be observed +between the value returned by the `totalSupply` and the actual circulating supply, +as the standard does not clearly define a process to create and destroy tokens. + +### Data + +The mint, send and burn processes can all make use of a `data` and `operatorData` fields +which are passed to any movement (mint, send or burn). +Those fields may be empty for simple use cases, +or they may contain valuable information related to the movement of tokens, +similar to information attached to a bank transfer by the sender or the bank itself. + +The use of a `data` field is equally present in other standard proposals such as [EIP223], +and was requested by multiple members of the community who reviewed this standard. + +### Hooks + +In most cases, [ERC20] requires two calls to safely transfer tokens to a contract without locking them. +A call from the sender, using the `approve` function +and a call from the recipient using `transferFrom`. +Furthermore, this requires extra communication between the parties which is not clearly defined. +Finally, holders can get confused between `transfer` and `approve`/`transferFrom`. +Using the former to transfer tokens to a contract will most likely result in locked tokens. + +Hooks allow streamlining of the sending process and offer a single way to send tokens to any recipient. +Thanks to the `tokensReceived` hook, contracts are able to react and prevent locking tokens upon reception. + +#### **Greater Control For Holders** + +The `tokensReceived` hook also allows holders to reject the reception of some tokens. +This gives greater control to holders who can accept or reject incoming tokens based on some parameters, +for example located in the `data` or `operatorData` fields. + +Following the same intentions and based on suggestions from the community, +the `tokensToSend` hook was added to give control over and prevent the movement of outgoing tokens. + +#### **[ERC1820] Registry** + +The [ERC1820] Registry allows holders to register their hooks. +Other alternatives were examined beforehand to link hooks and holders. + +The first was for hooks to be defined at the sender's or recipient's address. +This approach is similar to [EIP223] which proposes a `tokenFallback` function on recipient contracts +to be called when receiving tokens, +but improves on it by relying on [ERC165] for interface detection. +While straightforward to implement, this approach imposes several limitations. +In particular, the sender and recipient must be contracts in order to provide their implementation of the hooks. +Preventing externally owned addresses to benefit from hooks. +Existing contracts have a strong probability not to be compatible, +as they undoubtedly were unaware and do not define the new hooks. +Consequently existing smart contract infrastructure such as multisig wallets +which potentially hold large amounts of ether and tokens would need to be migrated to new updated contracts. + +The second approach considered was to use [ERC672] which offered pseudo-introspection for addresses using reverse-ENS. +However, this approach relied heavily on ENS, on top of which reverse lookup would need to be implemented. +Analysis of this approach promptly revealed a certain degree of complexity and security concerns +which would transcend the benefits of approach. + +The third solution—used in this standard—is to rely on a unique registry +where any address can register the addresses of contracts implementing the hooks on its behalf. +This approach has the advantage that externally owned accounts and contracts can benefit from hooks, +including existing contracts which can rely on hooks deployed on proxy contracts. + +The decision was made to keep this registry in a separate EIP, +as to not over complicate this standard. +More importantly, the registry is designed in a flexible fashion, +such that other EIPs and smart contract infrastructures can benefit from it +for their own use cases, outside the realm of [ERC777] and tokens. +The first proposal for this registry was [ERC820]. +Unfortunately, issues emanating from upgrades in the Solidity language to versions 0.5 and above +resulted in a bug in a separated part of the registry, which required changes. +This was discovered right after the last call period. +Attempts made to avoid creating a separate EIP, such as [ERC820a], were rejected. +Hence the standard for the registry used for [ERC777] became [ERC1820]. +[ERC1820] and [ERC820] are functionally equivalent. [ERC1820] simply contains the fix for newer versions of Solidity. + +### Operators + +The standard defines the concept of operators as any address which moves tokens. +While intuitively every address moves its own tokens, +separating the concepts of holder and operator allows for greater flexibility. +Primarily, this originates from the fact that the standard defines a mechanism for holders +to let other addresses become their operators. +Moreover, unlike the approve calls in [ERC20] where the role of an approved address is not clearly defined, +[ERC777] details the intent of and interactions with operators, +including an obligation for operators to be approved, +and an irrevocable right for any holder to revoke operators. + +#### **Default Operators** + +Default operators were added based on community demand for pre-approved operators. +That is operators which are approved for all holders by default. +For obvious security reasons, the list of default operators is defined at the token contract creation time, +and cannot be changed. +Any holder still has the right to revoke default operators. +One of the obvious advantages of default operators is to allow ether-less movements of tokens. +Default operators offer other usability advantages, +such as allowing token providers to offer functionality in a modular way, +and to reduce the complexity for holders to use features provided through operators. ## Backward Compatibility @@ -949,7 +1152,8 @@ If the token implements [ERC20], it MUST register the `ERC20Token` interface with its own address via [ERC1820]. This is done by calling the `setInterfaceImplementer` function on the ERC1820 registry with the token contract address as both the address and the implementer -and the `keccak256` hash of `ERC20Token` as the interface hash. +and the `keccak256` hash of `ERC20Token` (`0xaea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a`) +as the interface hash. If the contract has a switch to enable or disable ERC20 functions, every time the switch is triggered, the token MUST register or unregister the `ERC20Token` interface for its own address accordingly via ERC1820. @@ -992,17 +1196,23 @@ when sending, minting and transferring token via [ERC777] and [ERC20]: ERC777TokensRecipient
not registered regular address - continue - continue + continue contract MUST revert + SHOULD continue1 +> 1. +> The transaction SHOULD continue for clarity as ERC20 is not aware of hooks. +> However, this can result in accidentally locked tokens. +> If avoiding accidentally locked tokens is paramount, the transaction MAY revert. + + There is no particular action to take if `tokensToSend` is not implemented. -The transfer MUST proceed and only be canceled if another condition is not respected +The movement MUST proceed and only be canceled if another condition is not respected such as lack of funds or a `revert` in `tokensReceived` (if present). During a send, mint and burn, the respective `Sent`, `Minted` and `Burned` events MUST be emitted. @@ -1035,10 +1245,16 @@ Copyright and related rights waived via [CC0]. [operators]: #operators [ERC20]: https://eips.ethereum.org/EIPS/eip-20 +[ERC165]: https://eips.ethereum.org/EIPS/eip-165 +[ERC672]: https://github.com/ethereum/EIPs/issues/672 [ERC777]: https://eips.ethereum.org/EIPS/eip-777 +[ERC820]: https://eips.ethereum.org/EIPS/eip-820 +[ERC820a]: https://github.com/ethereum/EIPs/pull/1758 [ERC1820]: https://eips.ethereum.org/EIPS/eip-1820 [erc1820-set]: https://eips.ethereum.org/EIPS/eip-1820#set-an-interface-for-an-address +[0xjac]: https://github.com/0xjac [0xjac/ERC777]: https://github.com/0xjac/ERC777 +[master thesis]: https://github.com/0xjac/master-thesis [npm/erc777]: https://www.npmjs.com/package/erc777 [ref tests]: https://github.com/0xjac/ERC777/blob/master/test/ReferenceToken.test.js [reference implementation]: https://github.com/0xjac/ERC777/blob/master/contracts/examples/ReferenceToken.sol diff --git a/EIPS/eip-778.md b/EIPS/eip-778.md index 72d33157f4802..b0976c8784a74 100644 --- a/EIPS/eip-778.md +++ b/EIPS/eip-778.md @@ -39,12 +39,32 @@ The components of a node record are: - `signature`: cryptographic signature of record contents - `seq`: The sequence number, a 64-bit unsigned integer. Nodes should increase the number whenever the record changes and republish the record. -- The remainder of the record consists of arbitrary key/value pairs, which must be sorted - by key. Keys must be unique. +- The remainder of the record consists of arbitrary key/value pairs A record's signature is made and validated according to an *identity scheme*. The identity scheme is also responsible for deriving a node's address in the DHT. +The key/value pairs must be sorted by key and must be unique, i.e. any key may be present +only once. The keys can technically be any byte sequence, but ASCII text is preferred. Key +names in the table below have pre-defined meaning. + +| Key | Value | +|:------------|:-------------------------------------------| +| `id` | name of identity scheme, e.g. "v4" | +| `secp256k1` | compressed secp256k1 public key, 33 bytes | +| `ip` | IPv4 address, 4 bytes | +| `tcp` | TCP port, big endian integer | +| `udp` | UDP port, big endian integer | +| `ip6` | IPv6 address, 16 bytes | +| `tcp6` | IPv6-specific TCP port, big endian integer | +| `udp6` | IPv6-specific UDP port, big endian integer | + +All keys except `id` are optional, including IP addresses and ports. A record without +endpoint information is still valid as long as its signature is valid. If no `tcp6` / +`udp6` port is provided, the `tcp` / `udp` port applies to both IP addresses. Declaring +the same port number in both `tcp`, `tcp6` or `udp`, `udp6` should be avoided but doesn't +render the record invalid. + ### RLP Encoding The canonical encoding of a node record is an RLP list of `[signature, seq, k, v, ...]`. @@ -57,23 +77,17 @@ Records are signed and encoded as follows: signature = sign(content) record = [signature, seq, k, v, ...] -### Key/Value Pairs - -The keys in key/value pairs can technically be any byte sequence, but ASCII text is -preferred. The following keys are pre-defined: +### Text Encoding -| Key | Value | -|:------------|:------------------------------------------| -| `id` | name of identity scheme, e.g. "v4" | -| `secp256k1` | compressed secp256k1 public key, 33 bytes | -| `ip` | IP address, 4 or 16 bytes | -| `tcp` | TCP port, big endian integer | -| `udp` | UDP port, big endian integer | +The textual form of a node record is the base64 encoding of its RLP representation, +prefixed by `enr:`. Implementations should use the [URL-safe base64 alphabet][base64url] +and omit padding characters. ### "v4" Identity Scheme -This specification defines a single scheme to be used as the default. The "v4" scheme is -backwards-compatible with the cryptosystem used by Node Discovery v4. +This specification defines a single identity scheme to be used as the default until other +schemes are defined by further EIPs. The "v4" scheme is backwards-compatible with the +cryptosystem used by Node Discovery v4. - To sign record `content` with this scheme, apply the keccak256 hash function (as used by the EVM) to `content`, then create a signature of the hash. The resulting 64-byte @@ -99,19 +113,29 @@ in size-constrained protocols such as DNS. A record containing a IPv4 address, w using the "v4" scheme occupies roughly 120 bytes, leaving plenty of room for additional metadata. +You might wonder about the need for so many pre-defined keys related to IP addresses and +ports. This need arises because residential and mobile network setups often put IPv4 +behind NAT while IPv6 traffic—if supported—is directly routed to the same host. Declaring +both address types ensures a node is reachable from IPv4-only locations and those +supporting both protocols. + # Test Vectors -Example (valid) record: +This is an example record containing the IPv4 address `127.0.0.1` and UDP port `30303`. +The node ID is `a448f24c6d18e575453db13171562b71999873db5b286df957af199ec94617f7`. + +```text +enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8 +``` + +The record is signed using the "v4" identity scheme using sequence number `1` and this +private key: ```text -f884b8407098ad865b00a582051940cb9cf36836572411a4727878307701 -1599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11 -df72ecf1145ccb9c01826964827634826970847f00000189736563703235 -366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1 -400f3258cd31388375647082765f +b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291 ``` -The raw RLP structure of this record is: +The RLP structure of the record is: ```text [ @@ -128,14 +152,8 @@ The raw RLP structure of this record is: ] ``` -The record contains sequence number `1`. - -A v4 enode URL containing the same information (but no signature or sequence number): - -```text -enode://ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f@127.0.0.1:0?discport=30303 -``` - # Copyright Copyright and related rights waived via CC0. + +[base64url]: https://tools.ietf.org/html/rfc4648#section-5 diff --git a/EIPS/eip-779.md b/EIPS/eip-779.md index 4d18547193791..1d658b0854779 100644 --- a/EIPS/eip-779.md +++ b/EIPS/eip-779.md @@ -1,7 +1,7 @@ --- eip: 779 title: "Hardfork Meta: DAO Fork" -author: Casey Detrio +author: Casey Detrio (@cdetrio) type: Meta status: Final created: 2017-11-26 diff --git a/EIPS/eip-823.md b/EIPS/eip-823.md index 727af0cf04e4f..49152b45decfc 100644 --- a/EIPS/eip-823.md +++ b/EIPS/eip-823.md @@ -184,16 +184,16 @@ This event logs any new exchange that have taken place and have been spent immed event ExchangeAndSpent ( address _from, address _by, uint _value ,address _target ,address _to) ``` -### Diagramatic Explaination +### Diagramatic Explanation #### Exchanging Tokens -![token-exchange-standard-visual-representation-1](https://raw.githubusercontent.com/kashishkhullar/EIPs/master/assets/eip-823/eip-823-token-exchange-standard-visual-representation-1.PNG) +![token-exchange-standard-visual-representation-1](../assets/eip-823/eip-823-token-exchange-standard-visual-representation-1.PNG) NOTE: After the successful exchange the contract on right owns some tokens of the contract on the left. #### Exchanging And Spending Tokens -![token-exchange-standard-visual-representation-2](https://raw.githubusercontent.com/kashishkhullar/EIPs/master/assets/eip-823/eip-823-token-exchange-standard-visual-representation-2.PNG) +![token-exchange-standard-visual-representation-2](../assets/eip-823/eip-823-token-exchange-standard-visual-representation-2.PNG) NOTE: After the successful exchange the contract on right owns some tokens of the contract on the left. diff --git a/EIPS/eip-86.md b/EIPS/eip-86.md index 6b9494b9ecd8c..a76ccbc33464a 100644 --- a/EIPS/eip-86.md +++ b/EIPS/eip-86.md @@ -1,7 +1,7 @@ --- eip: 86 title: Abstraction of transaction origin and signature -author: Vitalik Buterin +author: Vitalik Buterin (@vbuterin) type: Standards Track category: Core status: Draft diff --git a/EIPS/eip-875.md b/EIPS/eip-875.md index af4424e56cd80..be9d5bdf63f24 100644 --- a/EIPS/eip-875.md +++ b/EIPS/eip-875.md @@ -1,9 +1,10 @@ --- eip: 875 -title: A better NFT standard +title: Simpler NFT standard with batching and native atomic swaps author: Weiwu Zhang , James Sangalli discussions-to: https://github.com/ethereum/EIPs/issues/875 -status: Draft +status: Last Call +review-period-end: 2019-07-29 type: Standards Track category: ERC created: 2018-02-08 @@ -63,7 +64,18 @@ Some protections need to be added to the message such as encoding the chain id, ## Interface ``` -contract ERC875 +contract ERC165 +{ + /// @notice Query if a contract implements an interface + /// @param interfaceID The interface identifier, as specified in ERC-165 + /// @dev Interface identification is specified in ERC-165. This function + /// uses less than 30,000 gas. + /// @return `true` if the contract implements `interfaceID` and + /// `interfaceID` is not 0xffffffff, `false` otherwise + function supportsInterface(bytes4 interfaceID) external view returns (bool); +} + +interface ERC875 /* is ERC165 */ { event Transfer(address indexed _from, address indexed _to, uint256[] tokenIndices); @@ -72,11 +84,17 @@ contract ERC875 function balanceOf(address _owner) public view returns (uint256[] _balances); function transfer(address _to, uint256[] _tokens) public; function transferFrom(address _from, address _to, uint256[] _tokens) public; +} - //optional - //function totalSupply() public constant returns (uint256 totalSupply); - function trade(uint256 expiryTimeStamp, uint256[] tokenIndices, uint8 v, bytes32 r, bytes32 s) public payable; - //function ownerOf(uint256 _tokenId) public view returns (address _owner); +//If you want the standard functions with atomic swap trading added +interface ERC875WithAtomicSwapTrading is ERC875 { + function trade( + uint256 expiryTimeStamp, + uint256[] tokenIndices, + uint8 v, + bytes32 r, + bytes32 s + ) public payable; } ``` diff --git a/EIPS/eip-897.md b/EIPS/eip-897.md index 163732702ab22..d0fdb2aa26090 100644 --- a/EIPS/eip-897.md +++ b/EIPS/eip-897.md @@ -6,7 +6,7 @@ type: Standards Track category: ERC status: Draft created: 2018-02-21 -discussions-to: https://github.com/ethereum/EIPs/pulls/897 +discussions-to: https://github.com/ethereum/EIPs/pull/897 --- ## Simple Summary diff --git a/EIPS/eip-918.md b/EIPS/eip-918.md index 1dc296e56d3dd..10047046b5e4b 100644 --- a/EIPS/eip-918.md +++ b/EIPS/eip-918.md @@ -66,7 +66,7 @@ bytes32 public adjustmentInterval; ``` #### challengeNumber -The current challenge number. It is expected tha a new challenge number is generated after a new reward is minted. +The current challenge number. It is expected that a new challenge number is generated after a new reward is minted. ``` solidity bytes32 public challengeNumber; @@ -145,7 +145,7 @@ contract AbstractERC918 is EIP918Interface { epochCount = _epoch(); - //every so often, readjust difficulty. Dont readjust when deploying + //every so often, readjust difficulty. Don't readjust when deploying if(epochCount % blocksPerReadjustment == 0){ _adjustDifficulty(); } @@ -273,7 +273,7 @@ contract ERC918Merged is AbstractERC918 { } /* - * @notice Externally facing merge function kept for backwards compatability with previous definition + * @notice Externally facing merge function kept for backwards compatibility with previous definition * * @param _nonce the solution nonce * @param _challenge_digest the keccak256 encoded challenge number + message sender + solution nonce @@ -442,7 +442,7 @@ Earlier versions of this standard incorporated a redundant 'challenge_digest' pa contract ERC918BackwardsCompatible is AbstractERC918 { /* - * @notice Externally facing mint function kept for backwards compatability with previous mint() definition + * @notice Externally facing mint function kept for backwards compatibility with previous mint() definition * @param _nonce the solution nonce * @param _challenge_digest the keccak256 encoded challenge number + message sender + solution nonce **/ diff --git a/EIPS/eip-998.md b/EIPS/eip-998.md index 88f0b9205245f..bc87b8b1fb20a 100644 --- a/EIPS/eip-998.md +++ b/EIPS/eip-998.md @@ -856,7 +856,7 @@ interface ERC998ERC721BottomUp { /// @return rootOwner The root owner at the top of tree of tokens and ERC998 magic value. function rootOwnerOf(uint256 _tokenId) external view returns (bytes32 rootOwner); - /// @notice Get the owner addess and parent token (if there is one) of a token + /// @notice Get the owner address and parent token (if there is one) of a token /// @param _tokenId The tokenId to query. /// @return tokenOwner The owner address of the token /// @return parentTokenId The parent owner of the token and ERC998 magic value @@ -947,7 +947,7 @@ Here is an example of a value returned by `rootOwnerOf`. #### tokenOwnerOf ```solidity -/// @notice Get the owner addess and parent token (if there is one) of a token +/// @notice Get the owner address and parent token (if there is one) of a token /// @param _tokenId The tokenId to query. /// @return tokenOwner The owner address of the token and ERC998 magic value. /// @return parentTokenId The parent owner of the token diff --git a/EIPS/eip-999.md b/EIPS/eip-999.md index 424770fd82037..ce0389d978dae 100644 --- a/EIPS/eip-999.md +++ b/EIPS/eip-999.md @@ -46,10 +46,10 @@ as reviewed, tested, and approved in ``` { - "object": "606060405234156200000d57fe5b5b6000808054806001018281620000259190620002d9565b916000526020600020900160005b6000909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200012081805480602002602001604051908101604052809291908181526020018280548015620000fd57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311620000b2575b505050505060016000620001286401000000000262001d46176401000000009004565b5b5062000330565b600060015411156200013a5760006000fd5b6200015981620001806401000000000262001d71176401000000009004565b620001798383620001c26401000000000262001d9c176401000000009004565b5b5b505050565b60006001541115620001925760006000fd5b80600281905550620001b7620002c16401000000000262001bcf176401000000009004565b6004819055505b5b50565b600060006001541115620001d65760006000fd5b600082111515620001e75760006000fd5b81835110151515620001f95760006000fd5b8251600181905550600090505b8251811015620002b35782818151811015156200021f57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff16600582600101610100811015156200025357fe5b0160005b508190555080600101610105600085848151811015156200027457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b80600101905062000206565b816000819055505b5b505050565b60006201518042811515620002d257fe5b0490505b90565b815481835581811511620003035781836000526020600020918201910162000302919062000308565b5b505050565b6200032d91905b80821115620003295760008160009055506001016200030f565b5090565b90565b611ebf80620003406000396000f300606060405236156100ef576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063173825d91461016d5780632f54bf6e146101a35780634123cb6b146101f157806352375093146102175780635c52c2f51461023d578063659010e71461024f5780637065cb4814610275578063746c9171146102ab578063797af627146102d1578063b20d30a91461030d578063b61d27f61461032d578063b75c7dc61461039c578063ba51a6df146103c0578063c2cf7326146103e0578063c41a360a1461043b578063f00d4b5d1461049b578063f1736d86146104f0575b61016b5b6000341115610168577fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c3334604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b5b565b005b341561017557fe5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610516565b005b34156101ab57fe5b6101d7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610659565b604051808215151515815260200191505060405180910390f35b34156101f957fe5b610201610691565b6040518082815260200191505060405180910390f35b341561021f57fe5b610227610697565b6040518082815260200191505060405180910390f35b341561024557fe5b61024d61069d565b005b341561025757fe5b61025f6106d7565b6040518082815260200191505060405180910390f35b341561027d57fe5b6102a9600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506106dd565b005b34156102b357fe5b6102bb610829565b6040518082815260200191505060405180910390f35b34156102d957fe5b6102f360048080356000191690602001909190505061082f565b604051808215151515815260200191505060405180910390f35b341561031557fe5b61032b6004808035906020019091905050610dcc565b005b341561033557fe5b61037e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919080359060200190820180359060200191909192905050610e06565b60405180826000191660001916815260200191505060405180910390f35b34156103a457fe5b6103be60048080356000191690602001909190505061127d565b005b34156103c857fe5b6103de6004808035906020019091905050611392565b005b34156103e857fe5b61042160048080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061141a565b604051808215151515815260200191505060405180910390f35b341561044357fe5b610459600480803590602001909190505061149c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104a357fe5b6104ee600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506114bf565b005b34156104f857fe5b610500611672565b6040518082815260200191505060405180910390f35b600060003660405180838380828437820191505092505050604051809103902061053f81611678565b156106535761010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561057f57610652565b600160015403600054111561059357610652565b6000600583610100811015156105a557fe5b0160005b5081905550600061010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506105e6611890565b6105ee6119d0565b7f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da83604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b505050565b6000600061010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541190505b919050565b60015481565b60045481565b6000366040518083838082843782019150509250505060405180910390206106c481611678565b156106d35760006003819055505b5b5b50565b60035481565b60003660405180838380828437820191505092505050604051809103902061070481611678565b156108245761071282610659565b1561071c57610823565b610724611890565b60fa600154101515610739576107386119d0565b5b60fa60015410151561074a57610823565b6001600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff1660056001546101008110151561078557fe5b0160005b508190555060015461010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c382604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b5050565b60005481565b600060008261083d81611678565b15610dc45760006101086000866000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415806108c757506000610108600086600019166000191681526020019081526020016000206001015414155b80610906575060006101086000866000191660001916815260200190815260200160002060020180546001816001161561010002031660029004905014155b15610dc25760006101086000866000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610a5057610a496101086000866000191660001916815260200190815260200160002060010154610108600087600019166000191681526020019081526020016000206002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a3f5780601f10610a1457610100808354040283529160200191610a3f565b820191906000526020600020905b815481529060010190602001808311610a2257829003601f168201915b5050505050611b37565b9150610b71565b6101086000856000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166101086000866000191660001916815260200190815260200160002060010154610108600087600019166000191681526020019081526020016000206002016040518082805460018160011615610100020316600290048015610b4a5780601f10610b1f57610100808354040283529160200191610b4a565b820191906000526020600020905b815481529060010190602001808311610b2d57829003601f168201915b505091505060006040518083038185876185025a03f1925050501515610b705760006000fd5b5b7fe3a3a4111a84df27d76b68dc721e65c7711605ea5eee4afd3a9c58195217365c338561010860008860001916600019168152602001908152602001600020600101546101086000896000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661010860008a6000191660001916815260200190815260200160002060020187604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186600019166000191681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610d475780601f10610d1c57610100808354040283529160200191610d47565b820191906000526020600020905b815481529060010190602001808311610d2a57829003601f168201915b505097505050505050505060405180910390a16101086000856000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160009055600282016000610db79190611be6565b505060019250610dc3565b5b5b5b5050919050565b600036604051808383808284378201915050925050506040518091039020610df381611678565b15610e0157816002819055505b5b5b5050565b60006000610e1333610659565b1561127357600084849050148015610e305750610e2f85611b51565b5b80610e3d57506001600054145b15610fed5760008673ffffffffffffffffffffffffffffffffffffffff161415610ea457610e9d8585858080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611b37565b9050610ef3565b8573ffffffffffffffffffffffffffffffffffffffff168585856040518083838082843782019150509250505060006040518083038185876185025a03f1925050501515610ef25760006000fd5b5b7f9738cd1a8777c86b011f7b01d87d484217dc6ab5154a9d41eda5d14af8caf292338688878786604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281038252858582818152602001925080828437820191505097505050505050505060405180910390a1611271565b6000364360405180848480828437820191505082815260200193505050506040518091039020915060006101086000846000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015611099575060006101086000846000191660001916815260200190815260200160002060010154145b80156110d85750600061010860008460001916600019168152602001908152602001600020600201805460018160011615610100020316600290049050145b1561118f57856101086000846000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550846101086000846000191660001916815260200190815260200160002060010181905550838361010860008560001916600019168152602001908152602001600020600201919061118d929190611c2e565b505b6111988261082f565b1515611270577f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328233878988886040518087600019166000191681526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b5b5b5b5b50949350505050565b60006000600061010560003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054925060008314156112be5761138c565b8260020a9150610106600085600019166000191681526020019081526020016000209050600082826001015416111561138b5780600001600081548092919060010191905055508181600101600082825403925050819055507fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b3385604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182600019166000191681526020019250505060405180910390a15b5b50505050565b6000366040518083838082843782019150509250505060405180910390206113b981611678565b15611415576001548211156113cd57611414565b816000819055506113dc611890565b7facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da826040518082815260200191505060405180910390a15b5b5b5050565b600060006000600061010660008760001916600019168152602001908152602001600020925061010560008673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561147f5760009350611493565b8160020a9050600081846001015416141593505b50505092915050565b6000600560018301610100811015156114b157fe5b0160005b505490505b919050565b60006000366040518083838082843782019150509250505060405180910390206114e881611678565b1561166b576114f683610659565b156115005761166a565b61010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561153b5761166a565b611543611890565b8273ffffffffffffffffffffffffffffffffffffffff166005836101008110151561156a57fe5b0160005b5081905550600061010560008673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508161010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15b5b5b50505050565b60025481565b600060006000600061010560003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054925060008314156116bb57611888565b6101066000866000191660001916815260200190815260200160002091506000826000015414156117455760005482600001819055506000826001018190555061010780548091906001016117109190611cae565b826002018190555084610107836002015481548110151561172d57fe5b906000526020600020900160005b5081600019169055505b8260020a90506000818360010154161415611887577fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda3386604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182600019166000191681526020019250505060405180910390a16001826000015411151561185e57610107610106600087600019166000191681526020019081526020016000206002015481548110151561180a57fe5b906000526020600020900160005b5060009055610106600086600019166000191681526020019081526020016000206000600082016000905560018201600090556002820160009055505060019350611888565b8160000160008154809291906001900391905055508082600101600082825417925050819055505b5b5b505050919050565b60006000610107805490509150600090505b818110156119bc576101086000610107838154811015156118bf57fe5b906000526020600020900160005b50546000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018201600090556002820160006119269190611be6565b505060006001026101078281548110151561193d57fe5b906000526020600020900160005b5054600019161415156119b05761010660006101078381548110151561196d57fe5b906000526020600020900160005b505460001916600019168152602001908152602001600020600060008201600090556001820160009055600282016000905550505b5b8060010190506118a2565b61010760006119cb9190611cda565b5b5050565b6000600190505b600154811015611b33575b60015481108015611a095750600060058261010081101515611a0057fe5b0160005b505414155b15611a1b5780806001019150506119e2565b5b6001600154118015611a4557506000600560015461010081101515611a3d57fe5b0160005b5054145b15611a625760016000815480929190600190039190505550611a1c565b60015481108015611a8b57506000600560015461010081101515611a8257fe5b0160005b505414155b8015611aac5750600060058261010081101515611aa457fe5b0160005b5054145b15611b2e57600560015461010081101515611ac357fe5b0160005b505460058261010081101515611ad957fe5b0160005b508190555080610105600060058461010081101515611af857fe5b0160005b50548152602001908152602001600020819055506000600560015461010081101515611b2457fe5b0160005b50819055505b6119d7565b5b50565b600081516020830184f09050803b15610000575b92915050565b6000611b5c33610659565b15611bc957600454611b6c611bcf565b1115611b89576000600381905550611b82611bcf565b6004819055505b600354826003540110158015611ba55750600254826003540111155b15611bc3578160036000828254019250508190555060019050611bc8565b600090505b5b5b919050565b60006201518042811515611bdf57fe5b0490505b90565b50805460018160011615610100020316600290046000825580601f10611c0c5750611c2b565b601f016020900490600052602060002090810190611c2a9190611cfc565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c6f57803560ff1916838001178555611c9d565b82800160010185558215611c9d579182015b82811115611c9c578235825591602001919060010190611c81565b5b509050611caa9190611cfc565b5090565b815481835581811511611cd557818360005260206000209182019101611cd49190611d21565b5b505050565b5080546000825590600052602060002090810190611cf89190611d21565b5b50565b611d1e91905b80821115611d1a576000816000905550600101611d02565b5090565b90565b611d4391905b80821115611d3f576000816000905550600101611d27565b5090565b90565b60006001541115611d575760006000fd5b611d6081611d71565b611d6a8383611d9c565b5b5b505050565b60006001541115611d825760006000fd5b80600281905550611d91611bcf565b6004819055505b5b50565b600060006001541115611daf5760006000fd5b600082111515611dbf5760006000fd5b81835110151515611dd05760006000fd5b8251600181905550600090505b8251811015611e85578281815181101515611df457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1660058260010161010081101515611e2757fe5b0160005b50819055508060010161010560008584815181101515611e4757fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b806001019050611ddd565b816000819055505b5b5050505600a165627a7a7230582016889f0740f073d397f9d00b0d19900fb050b957e3e2942f861085beb9baab180029", - "opcodes": "PUSH1 0x60 PUSH1 0x40 MSTORE CALLVALUE ISZERO PUSH3 0xD JUMPI INVALID JUMPDEST JUMPDEST PUSH1 0x0 DUP1 DUP1 SLOAD DUP1 PUSH1 0x1 ADD DUP3 DUP2 PUSH3 0x25 SWAP2 SWAP1 PUSH3 0x2D9 JUMP JUMPDEST SWAP2 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST PUSH1 0x0 SWAP1 SWAP2 SWAP1 SWAP2 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP POP PUSH3 0x120 DUP2 DUP1 SLOAD DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD DUP1 ISZERO PUSH3 0xFD JUMPI PUSH1 0x20 MUL DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 ADD SWAP1 DUP1 DUP4 GT PUSH3 0xB2 JUMPI JUMPDEST POP POP POP POP POP PUSH1 0x1 PUSH1 0x0 PUSH3 0x128 PUSH5 0x100000000 MUL PUSH3 0x1D46 OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST JUMPDEST POP PUSH3 0x330 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH3 0x13A JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH3 0x159 DUP2 PUSH3 0x180 PUSH5 0x100000000 MUL PUSH3 0x1D71 OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST PUSH3 0x179 DUP4 DUP4 PUSH3 0x1C2 PUSH5 0x100000000 MUL PUSH3 0x1D9C OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH3 0x192 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP1 PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x1B7 PUSH3 0x2C1 PUSH5 0x100000000 MUL PUSH3 0x1BCF OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST PUSH1 0x4 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH3 0x1D6 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH1 0x0 DUP3 GT ISZERO ISZERO PUSH3 0x1E7 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP2 DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH3 0x1F9 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP3 MLOAD PUSH1 0x1 DUP2 SWAP1 SSTORE POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP3 MLOAD DUP2 LT ISZERO PUSH3 0x2B3 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0x21F JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 DUP3 PUSH1 0x1 ADD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH3 0x253 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x1 ADD PUSH2 0x105 PUSH1 0x0 DUP6 DUP5 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0x274 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP JUMPDEST DUP1 PUSH1 0x1 ADD SWAP1 POP PUSH3 0x206 JUMP JUMPDEST DUP2 PUSH1 0x0 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH3 0x15180 TIMESTAMP DUP2 ISZERO ISZERO PUSH3 0x2D2 JUMPI INVALID JUMPDEST DIV SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 ISZERO GT PUSH3 0x303 JUMPI DUP2 DUP4 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP2 DUP3 ADD SWAP2 ADD PUSH3 0x302 SWAP2 SWAP1 PUSH3 0x308 JUMP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH3 0x32D SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x329 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x30F JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x1EBF DUP1 PUSH3 0x340 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x60 PUSH1 0x40 MSTORE CALLDATASIZE ISZERO PUSH2 0xEF JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x173825D9 EQ PUSH2 0x16D JUMPI DUP1 PUSH4 0x2F54BF6E EQ PUSH2 0x1A3 JUMPI DUP1 PUSH4 0x4123CB6B EQ PUSH2 0x1F1 JUMPI DUP1 PUSH4 0x52375093 EQ PUSH2 0x217 JUMPI DUP1 PUSH4 0x5C52C2F5 EQ PUSH2 0x23D JUMPI DUP1 PUSH4 0x659010E7 EQ PUSH2 0x24F JUMPI DUP1 PUSH4 0x7065CB48 EQ PUSH2 0x275 JUMPI DUP1 PUSH4 0x746C9171 EQ PUSH2 0x2AB JUMPI DUP1 PUSH4 0x797AF627 EQ PUSH2 0x2D1 JUMPI DUP1 PUSH4 0xB20D30A9 EQ PUSH2 0x30D JUMPI DUP1 PUSH4 0xB61D27F6 EQ PUSH2 0x32D JUMPI DUP1 PUSH4 0xB75C7DC6 EQ PUSH2 0x39C JUMPI DUP1 PUSH4 0xBA51A6DF EQ PUSH2 0x3C0 JUMPI DUP1 PUSH4 0xC2CF7326 EQ PUSH2 0x3E0 JUMPI DUP1 PUSH4 0xC41A360A EQ PUSH2 0x43B JUMPI DUP1 PUSH4 0xF00D4B5D EQ PUSH2 0x49B JUMPI DUP1 PUSH4 0xF1736D86 EQ PUSH2 0x4F0 JUMPI JUMPDEST PUSH2 0x16B JUMPDEST PUSH1 0x0 CALLVALUE GT ISZERO PUSH2 0x168 JUMPI PUSH32 0xE1FFFCC4923D04B559F4D29A8BFC6CDA04EB5B0D3C460751C2402C5C5CC9109C CALLER CALLVALUE PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x175 JUMPI INVALID JUMPDEST PUSH2 0x1A1 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x516 JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x1AB JUMPI INVALID JUMPDEST PUSH2 0x1D7 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x659 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x1F9 JUMPI INVALID JUMPDEST PUSH2 0x201 PUSH2 0x691 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x21F JUMPI INVALID JUMPDEST PUSH2 0x227 PUSH2 0x697 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x245 JUMPI INVALID JUMPDEST PUSH2 0x24D PUSH2 0x69D JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x257 JUMPI INVALID JUMPDEST PUSH2 0x25F PUSH2 0x6D7 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x27D JUMPI INVALID JUMPDEST PUSH2 0x2A9 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x6DD JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x2B3 JUMPI INVALID JUMPDEST PUSH2 0x2BB PUSH2 0x829 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x2D9 JUMPI INVALID JUMPDEST PUSH2 0x2F3 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x82F JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x315 JUMPI INVALID JUMPDEST PUSH2 0x32B PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0xDCC JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x335 JUMPI INVALID JUMPDEST PUSH2 0x37E PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP3 ADD DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP2 SWAP1 SWAP2 SWAP3 SWAP1 POP POP PUSH2 0xE06 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x3A4 JUMPI INVALID JUMPDEST PUSH2 0x3BE PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x127D JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x3C8 JUMPI INVALID JUMPDEST PUSH2 0x3DE PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x1392 JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x3E8 JUMPI INVALID JUMPDEST PUSH2 0x421 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x141A JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x443 JUMPI INVALID JUMPDEST PUSH2 0x459 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x149C JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x4A3 JUMPI INVALID JUMPDEST PUSH2 0x4EE PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x14BF JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x4F8 JUMPI INVALID JUMPDEST PUSH2 0x500 PUSH2 0x1672 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x53F DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x653 JUMPI PUSH2 0x105 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP2 POP PUSH1 0x0 DUP3 EQ ISZERO PUSH2 0x57F JUMPI PUSH2 0x652 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 SLOAD SUB PUSH1 0x0 SLOAD GT ISZERO PUSH2 0x593 JUMPI PUSH2 0x652 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 DUP4 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x5A5 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH2 0x5E6 PUSH2 0x1890 JUMP JUMPDEST PUSH2 0x5EE PUSH2 0x19D0 JUMP JUMPDEST PUSH32 0x58619076ADF5BB0943D100EF88D52D7C3FD691B19D3A9071B555B651FBF418DA DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD GT SWAP1 POP JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x1 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x4 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x6C4 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x6D3 JUMPI PUSH1 0x0 PUSH1 0x3 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x3 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x704 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x824 JUMPI PUSH2 0x712 DUP3 PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x71C JUMPI PUSH2 0x823 JUMP JUMPDEST PUSH2 0x724 PUSH2 0x1890 JUMP JUMPDEST PUSH1 0xFA PUSH1 0x1 SLOAD LT ISZERO ISZERO PUSH2 0x739 JUMPI PUSH2 0x738 PUSH2 0x19D0 JUMP JUMPDEST JUMPDEST PUSH1 0xFA PUSH1 0x1 SLOAD LT ISZERO ISZERO PUSH2 0x74A JUMPI PUSH2 0x823 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 ADD SWAP2 SWAP1 POP SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x785 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP PUSH1 0x1 SLOAD PUSH2 0x105 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH32 0x994A936646FE87FFE4F1E469D3D6AA417D6B855598397F323DE5B449F765F0C3 DUP3 PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 DUP3 PUSH2 0x83D DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0xDC4 JUMPI PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO DUP1 PUSH2 0x8C7 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD EQ ISZERO JUMPDEST DUP1 PUSH2 0x906 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 POP EQ ISZERO JUMPDEST ISZERO PUSH2 0xDC2 JUMPI PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA50 JUMPI PUSH2 0xA49 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD PUSH2 0x108 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xA3F JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xA14 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xA3F JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xA22 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP PUSH2 0x1B37 JUMP JUMPDEST SWAP2 POP PUSH2 0xB71 JUMP JUMPDEST PUSH2 0x108 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD PUSH2 0x108 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xB4A JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xB1F JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xB4A JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xB2D JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 PUSH2 0x8502 GAS SUB CALL SWAP3 POP POP POP ISZERO ISZERO PUSH2 0xB70 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST JUMPDEST PUSH32 0xE3A3A4111A84DF27D76B68DC721E65C7711605EA5EEE4AFD3A9C58195217365C CALLER DUP6 PUSH2 0x108 PUSH1 0x0 DUP9 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD PUSH2 0x108 PUSH1 0x0 DUP10 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x108 PUSH1 0x0 DUP11 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP8 PUSH1 0x40 MLOAD DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD DUP6 DUP2 MSTORE PUSH1 0x20 ADD DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP2 DUP2 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xD47 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xD1C JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xD47 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xD2A JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP8 POP POP POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 PUSH2 0x108 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD SWAP1 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 PUSH2 0xDB7 SWAP2 SWAP1 PUSH2 0x1BE6 JUMP JUMPDEST POP POP PUSH1 0x1 SWAP3 POP PUSH2 0xDC3 JUMP JUMPDEST JUMPDEST JUMPDEST JUMPDEST POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0xDF3 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0xE01 JUMPI DUP2 PUSH1 0x2 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH2 0xE13 CALLER PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x1273 JUMPI PUSH1 0x0 DUP5 DUP5 SWAP1 POP EQ DUP1 ISZERO PUSH2 0xE30 JUMPI POP PUSH2 0xE2F DUP6 PUSH2 0x1B51 JUMP JUMPDEST JUMPDEST DUP1 PUSH2 0xE3D JUMPI POP PUSH1 0x1 PUSH1 0x0 SLOAD EQ JUMPDEST ISZERO PUSH2 0xFED JUMPI PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xEA4 JUMPI PUSH2 0xE9D DUP6 DUP6 DUP6 DUP1 DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP4 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP POP POP POP POP PUSH2 0x1B37 JUMP JUMPDEST SWAP1 POP PUSH2 0xEF3 JUMP JUMPDEST DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 DUP6 DUP6 PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 PUSH2 0x8502 GAS SUB CALL SWAP3 POP POP POP ISZERO ISZERO PUSH2 0xEF2 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST JUMPDEST PUSH32 0x9738CD1A8777C86B011F7B01D87D484217DC6AB5154A9D41EDA5D14AF8CAF292 CALLER DUP7 DUP9 DUP8 DUP8 DUP7 PUSH1 0x40 MLOAD DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP7 DUP2 MSTORE PUSH1 0x20 ADD DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP6 DUP6 DUP3 DUP2 DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP8 POP POP POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 PUSH2 0x1271 JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE NUMBER PUSH1 0x40 MLOAD DUP1 DUP5 DUP5 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP4 POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 SWAP2 POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ DUP1 ISZERO PUSH2 0x1099 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD EQ JUMPDEST DUP1 ISZERO PUSH2 0x10D8 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 POP EQ JUMPDEST ISZERO PUSH2 0x118F JUMPI DUP6 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP DUP5 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD DUP2 SWAP1 SSTORE POP DUP4 DUP4 PUSH2 0x108 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD SWAP2 SWAP1 PUSH2 0x118D SWAP3 SWAP2 SWAP1 PUSH2 0x1C2E JUMP JUMPDEST POP JUMPDEST PUSH2 0x1198 DUP3 PUSH2 0x82F JUMP JUMPDEST ISZERO ISZERO PUSH2 0x1270 JUMPI PUSH32 0x1733CBB53659D713B79580F79F3F9FF215F78A7C7AA45890F3B89FC5CDDFBF32 DUP3 CALLER DUP8 DUP10 DUP9 DUP9 PUSH1 0x40 MLOAD DUP1 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP6 DUP2 MSTORE PUSH1 0x20 ADD DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP5 DUP3 DUP2 DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP8 POP POP POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST JUMPDEST JUMPDEST POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP3 POP PUSH1 0x0 DUP4 EQ ISZERO PUSH2 0x12BE JUMPI PUSH2 0x138C JUMP JUMPDEST DUP3 PUSH1 0x2 EXP SWAP2 POP PUSH2 0x106 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SWAP1 POP PUSH1 0x0 DUP3 DUP3 PUSH1 0x1 ADD SLOAD AND GT ISZERO PUSH2 0x138B JUMPI DUP1 PUSH1 0x0 ADD PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 ADD SWAP2 SWAP1 POP SSTORE POP DUP2 DUP2 PUSH1 0x1 ADD PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH32 0xC7FB647E59B18047309AA15AAD418E5D7CA96D173AD704F1031A2C3D7591734B CALLER DUP6 PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x13B9 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x1415 JUMPI PUSH1 0x1 SLOAD DUP3 GT ISZERO PUSH2 0x13CD JUMPI PUSH2 0x1414 JUMP JUMPDEST DUP2 PUSH1 0x0 DUP2 SWAP1 SSTORE POP PUSH2 0x13DC PUSH2 0x1890 JUMP JUMPDEST PUSH32 0xACBDB084C721332AC59F9B8E392196C9EB0E4932862DA8EB9BEAF0DAD4F550DA DUP3 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH2 0x106 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SWAP3 POP PUSH2 0x105 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP2 POP PUSH1 0x0 DUP3 EQ ISZERO PUSH2 0x147F JUMPI PUSH1 0x0 SWAP4 POP PUSH2 0x1493 JUMP JUMPDEST DUP2 PUSH1 0x2 EXP SWAP1 POP PUSH1 0x0 DUP2 DUP5 PUSH1 0x1 ADD SLOAD AND EQ ISZERO SWAP4 POP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 DUP4 ADD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x14B1 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD SWAP1 POP JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x14E8 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x166B JUMPI PUSH2 0x14F6 DUP4 PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x1500 JUMPI PUSH2 0x166A JUMP JUMPDEST PUSH2 0x105 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP2 POP PUSH1 0x0 DUP3 EQ ISZERO PUSH2 0x153B JUMPI PUSH2 0x166A JUMP JUMPDEST PUSH2 0x1543 PUSH2 0x1890 JUMP JUMPDEST DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 DUP4 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x156A JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP DUP2 PUSH2 0x105 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH32 0xB532073B38C83145E3E5135377A08BF9AAB55BC0FD7C1179CD4FB995D2A5159C DUP5 DUP5 PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x2 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP3 POP PUSH1 0x0 DUP4 EQ ISZERO PUSH2 0x16BB JUMPI PUSH2 0x1888 JUMP JUMPDEST PUSH2 0x106 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SWAP2 POP PUSH1 0x0 DUP3 PUSH1 0x0 ADD SLOAD EQ ISZERO PUSH2 0x1745 JUMPI PUSH1 0x0 SLOAD DUP3 PUSH1 0x0 ADD DUP2 SWAP1 SSTORE POP PUSH1 0x0 DUP3 PUSH1 0x1 ADD DUP2 SWAP1 SSTORE POP PUSH2 0x107 DUP1 SLOAD DUP1 SWAP2 SWAP1 PUSH1 0x1 ADD PUSH2 0x1710 SWAP2 SWAP1 PUSH2 0x1CAE JUMP JUMPDEST DUP3 PUSH1 0x2 ADD DUP2 SWAP1 SSTORE POP DUP5 PUSH2 0x107 DUP4 PUSH1 0x2 ADD SLOAD DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x172D JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP DUP2 PUSH1 0x0 NOT AND SWAP1 SSTORE POP JUMPDEST DUP3 PUSH1 0x2 EXP SWAP1 POP PUSH1 0x0 DUP2 DUP4 PUSH1 0x1 ADD SLOAD AND EQ ISZERO PUSH2 0x1887 JUMPI PUSH32 0xE1C52DC63B719ADE82E8BEA94CC41A0D5D28E4AAF536ADB5E9CCCC9FF8C1AEDA CALLER DUP7 PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 PUSH1 0x1 DUP3 PUSH1 0x0 ADD SLOAD GT ISZERO ISZERO PUSH2 0x185E JUMPI PUSH2 0x107 PUSH2 0x106 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD SLOAD DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x180A JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP PUSH1 0x0 SWAP1 SSTORE PUSH2 0x106 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE POP POP PUSH1 0x1 SWAP4 POP PUSH2 0x1888 JUMP JUMPDEST DUP2 PUSH1 0x0 ADD PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 SWAP1 SUB SWAP2 SWAP1 POP SSTORE POP DUP1 DUP3 PUSH1 0x1 ADD PUSH1 0x0 DUP3 DUP3 SLOAD OR SWAP3 POP POP DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH2 0x107 DUP1 SLOAD SWAP1 POP SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP2 DUP2 LT ISZERO PUSH2 0x19BC JUMPI PUSH2 0x108 PUSH1 0x0 PUSH2 0x107 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x18BF JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD SWAP1 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 PUSH2 0x1926 SWAP2 SWAP1 PUSH2 0x1BE6 JUMP JUMPDEST POP POP PUSH1 0x0 PUSH1 0x1 MUL PUSH2 0x107 DUP3 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x193D JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x0 NOT AND EQ ISZERO ISZERO PUSH2 0x19B0 JUMPI PUSH2 0x106 PUSH1 0x0 PUSH2 0x107 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x196D JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE POP POP JUMPDEST JUMPDEST DUP1 PUSH1 0x1 ADD SWAP1 POP PUSH2 0x18A2 JUMP JUMPDEST PUSH2 0x107 PUSH1 0x0 PUSH2 0x19CB SWAP2 SWAP1 PUSH2 0x1CDA JUMP JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SWAP1 POP JUMPDEST PUSH1 0x1 SLOAD DUP2 LT ISZERO PUSH2 0x1B33 JUMPI JUMPDEST PUSH1 0x1 SLOAD DUP2 LT DUP1 ISZERO PUSH2 0x1A09 JUMPI POP PUSH1 0x0 PUSH1 0x5 DUP3 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1A00 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ ISZERO JUMPDEST ISZERO PUSH2 0x1A1B JUMPI DUP1 DUP1 PUSH1 0x1 ADD SWAP2 POP POP PUSH2 0x19E2 JUMP JUMPDEST JUMPDEST PUSH1 0x1 PUSH1 0x1 SLOAD GT DUP1 ISZERO PUSH2 0x1A45 JUMPI POP PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1A3D JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ JUMPDEST ISZERO PUSH2 0x1A62 JUMPI PUSH1 0x1 PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 SWAP1 SUB SWAP2 SWAP1 POP SSTORE POP PUSH2 0x1A1C JUMP JUMPDEST PUSH1 0x1 SLOAD DUP2 LT DUP1 ISZERO PUSH2 0x1A8B JUMPI POP PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1A82 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ ISZERO JUMPDEST DUP1 ISZERO PUSH2 0x1AAC JUMPI POP PUSH1 0x0 PUSH1 0x5 DUP3 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AA4 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ JUMPDEST ISZERO PUSH2 0x1B2E JUMPI PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AC3 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x5 DUP3 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AD9 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP DUP1 PUSH2 0x105 PUSH1 0x0 PUSH1 0x5 DUP5 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AF8 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1B24 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP JUMPDEST PUSH2 0x19D7 JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD PUSH1 0x20 DUP4 ADD DUP5 CREATE SWAP1 POP DUP1 EXTCODESIZE ISZERO PUSH2 0x0 JUMPI JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1B5C CALLER PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x1BC9 JUMPI PUSH1 0x4 SLOAD PUSH2 0x1B6C PUSH2 0x1BCF JUMP JUMPDEST GT ISZERO PUSH2 0x1B89 JUMPI PUSH1 0x0 PUSH1 0x3 DUP2 SWAP1 SSTORE POP PUSH2 0x1B82 PUSH2 0x1BCF JUMP JUMPDEST PUSH1 0x4 DUP2 SWAP1 SSTORE POP JUMPDEST PUSH1 0x3 SLOAD DUP3 PUSH1 0x3 SLOAD ADD LT ISZERO DUP1 ISZERO PUSH2 0x1BA5 JUMPI POP PUSH1 0x2 SLOAD DUP3 PUSH1 0x3 SLOAD ADD GT ISZERO JUMPDEST ISZERO PUSH2 0x1BC3 JUMPI DUP2 PUSH1 0x3 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH1 0x1 SWAP1 POP PUSH2 0x1BC8 JUMP JUMPDEST PUSH1 0x0 SWAP1 POP JUMPDEST JUMPDEST JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH3 0x15180 TIMESTAMP DUP2 ISZERO ISZERO PUSH2 0x1BDF JUMPI INVALID JUMPDEST DIV SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST POP DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV PUSH1 0x0 DUP3 SSTORE DUP1 PUSH1 0x1F LT PUSH2 0x1C0C JUMPI POP PUSH2 0x1C2B JUMP JUMPDEST PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1C2A SWAP2 SWAP1 PUSH2 0x1CFC JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH2 0x1C6F JUMPI DUP1 CALLDATALOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH2 0x1C9D JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH2 0x1C9D JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH2 0x1C9C JUMPI DUP3 CALLDATALOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH2 0x1C81 JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH2 0x1CAA SWAP2 SWAP1 PUSH2 0x1CFC JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 ISZERO GT PUSH2 0x1CD5 JUMPI DUP2 DUP4 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0x1CD4 SWAP2 SWAP1 PUSH2 0x1D21 JUMP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST POP DUP1 SLOAD PUSH1 0x0 DUP3 SSTORE SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1CF8 SWAP2 SWAP1 PUSH2 0x1D21 JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH2 0x1D1E SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1D1A JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH2 0x1D02 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x1D43 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1D3F JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH2 0x1D27 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH2 0x1D57 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH2 0x1D60 DUP2 PUSH2 0x1D71 JUMP JUMPDEST PUSH2 0x1D6A DUP4 DUP4 PUSH2 0x1D9C JUMP JUMPDEST JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH2 0x1D82 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP1 PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH2 0x1D91 PUSH2 0x1BCF JUMP JUMPDEST PUSH1 0x4 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH2 0x1DAF JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH1 0x0 DUP3 GT ISZERO ISZERO PUSH2 0x1DBF JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP2 DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0x1DD0 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP3 MLOAD PUSH1 0x1 DUP2 SWAP1 SSTORE POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP3 MLOAD DUP2 LT ISZERO PUSH2 0x1E85 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1DF4 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 DUP3 PUSH1 0x1 ADD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1E27 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x1 ADD PUSH2 0x105 PUSH1 0x0 DUP6 DUP5 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1E47 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP JUMPDEST DUP1 PUSH1 0x1 ADD SWAP1 POP PUSH2 0x1DDD JUMP JUMPDEST DUP2 PUSH1 0x0 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP POP POP JUMP STOP LOG1 PUSH6 0x627A7A723058 SHA3 AND DUP9 SWAP16 SMOD BLOCKHASH CREATE PUSH20 0xD397F9D00B0D19900FB050B957E3E2942F861085 0xbe 0xb9 0xba 0xab XOR STOP 0x29 ", - "sourceMap": "2715:10853:0:-;;;3523:112;;;;;;;3552:18;3574:8;:27;;;;;;;;;;;:::i;:::-;;;;;;;;;;;3596:3;3574:27;;;;;;;;;;;;;;;;;;;;;;;3605:26;3616:8;3605:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3626:1;3629;3605:10;;;;;:26;;;:::i;:::-;3523:112;;2715:10853;;7697:168;7585:1;7571:11;;:15;7567:26;;;7588:5;;;7567:26;7800:23;7813:9;7800:12;;;;;:23;;;:::i;:::-;7827:34;7842:7;7851:9;7827:14;;;;;:34;;;:::i;:::-;7595:1;7697:168;;;;:::o;6966:115::-;7585:1;7571:11;;:15;7567:26;;;7588:5;;;7567:26;7048:6;7033:12;:21;;;;7070:7;:5;;;;;:7;;;:::i;:::-;7058:9;:19;;;;7595:1;6966:115;;:::o;3977:349::-;4171:6;7585:1;7571:11;;:15;7567:26;;;7588:5;;;7567:26;4088:1;4076:9;:13;4068:22;;;;;;;;4120:9;4102:7;:14;:27;;4094:36;;;;;;;;4148:7;:14;4134:11;:28;;;;4180:1;4171:10;;4166:131;4187:7;:14;4183:1;:18;4166:131;;;4238:7;4246:1;4238:10;;;;;;;;;;;;;;;;;;4233:16;;4215:8;4228:1;4224;:5;4215:15;;;;;;;;;;;;:34;;;;;4291:1;4287;:5;4254:12;:30;4272:7;4280:1;4272:10;;;;;;;;;;;;;;;;;;4267:16;;4254:30;;;;;;;;;;;:38;;;;4166:131;4203:3;;;;;4166:131;;;4313:9;4300:10;:22;;;;7595:1;3977:349;;;;:::o;12529:73::-;12572:4;12593:6;12587:3;:12;;;;;;;;12580:19;;12529:73;;:::o;2715:10853::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;", - "linkReferences": {} + "object": "606060405234156200000d57fe5b5b6000808054806001018281620000259190620002d9565b916000526020600020900160005b6000909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200012081805480602002602001604051908101604052809291908181526020018280548015620000fd57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311620000b2575b505050505060016000620001286401000000000262001d46176401000000009004565b5b5062000330565b600060015411156200013a5760006000fd5b6200015981620001806401000000000262001d71176401000000009004565b620001798383620001c26401000000000262001d9c176401000000009004565b5b5b505050565b60006001541115620001925760006000fd5b80600281905550620001b7620002c16401000000000262001bcf176401000000009004565b6004819055505b5b50565b600060006001541115620001d65760006000fd5b600082111515620001e75760006000fd5b81835110151515620001f95760006000fd5b8251600181905550600090505b8251811015620002b35782818151811015156200021f57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff16600582600101610100811015156200025357fe5b0160005b508190555080600101610105600085848151811015156200027457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b80600101905062000206565b816000819055505b5b505050565b60006201518042811515620002d257fe5b0490505b90565b815481835581811511620003035781836000526020600020918201910162000302919062000308565b5b505050565b6200032d91905b80821115620003295760008160009055506001016200030f565b5090565b90565b611ebf80620003406000396000f300606060405236156100ef576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063173825d91461016d5780632f54bf6e146101a35780634123cb6b146101f157806352375093146102175780635c52c2f51461023d578063659010e71461024f5780637065cb4814610275578063746c9171146102ab578063797af627146102d1578063b20d30a91461030d578063b61d27f61461032d578063b75c7dc61461039c578063ba51a6df146103c0578063c2cf7326146103e0578063c41a360a1461043b578063f00d4b5d1461049b578063f1736d86146104f0575b61016b5b6000341115610168577fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c3334604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b5b565b005b341561017557fe5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610516565b005b34156101ab57fe5b6101d7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610659565b604051808215151515815260200191505060405180910390f35b34156101f957fe5b610201610691565b6040518082815260200191505060405180910390f35b341561021f57fe5b610227610697565b6040518082815260200191505060405180910390f35b341561024557fe5b61024d61069d565b005b341561025757fe5b61025f6106d7565b6040518082815260200191505060405180910390f35b341561027d57fe5b6102a9600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506106dd565b005b34156102b357fe5b6102bb610829565b6040518082815260200191505060405180910390f35b34156102d957fe5b6102f360048080356000191690602001909190505061082f565b604051808215151515815260200191505060405180910390f35b341561031557fe5b61032b6004808035906020019091905050610dcc565b005b341561033557fe5b61037e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919080359060200190820180359060200191909192905050610e06565b60405180826000191660001916815260200191505060405180910390f35b34156103a457fe5b6103be60048080356000191690602001909190505061127d565b005b34156103c857fe5b6103de6004808035906020019091905050611392565b005b34156103e857fe5b61042160048080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061141a565b604051808215151515815260200191505060405180910390f35b341561044357fe5b610459600480803590602001909190505061149c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104a357fe5b6104ee600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506114bf565b005b34156104f857fe5b610500611672565b6040518082815260200191505060405180910390f35b600060003660405180838380828437820191505092505050604051809103902061053f81611678565b156106535761010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561057f57610652565b600160015403600054111561059357610652565b6000600583610100811015156105a557fe5b0160005b5081905550600061010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506105e6611890565b6105ee6119d0565b7f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da83604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b505050565b6000600061010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541190505b919050565b60015481565b60045481565b6000366040518083838082843782019150509250505060405180910390206106c481611678565b156106d35760006003819055505b5b5b50565b60035481565b60003660405180838380828437820191505092505050604051809103902061070481611678565b156108245761071282610659565b1561071c57610823565b610724611890565b60fa600154101515610739576107386119d0565b5b60fa60015410151561074a57610823565b6001600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff1660056001546101008110151561078557fe5b0160005b508190555060015461010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c382604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b5050565b60005481565b600060008261083d81611678565b15610dc45760006101086000866000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415806108c757506000610108600086600019166000191681526020019081526020016000206001015414155b80610906575060006101086000866000191660001916815260200190815260200160002060020180546001816001161561010002031660029004905014155b15610dc25760006101086000866000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610a5057610a496101086000866000191660001916815260200190815260200160002060010154610108600087600019166000191681526020019081526020016000206002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a3f5780601f10610a1457610100808354040283529160200191610a3f565b820191906000526020600020905b815481529060010190602001808311610a2257829003601f168201915b5050505050611b37565b9150610b71565b6101086000856000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166101086000866000191660001916815260200190815260200160002060010154610108600087600019166000191681526020019081526020016000206002016040518082805460018160011615610100020316600290048015610b4a5780601f10610b1f57610100808354040283529160200191610b4a565b820191906000526020600020905b815481529060010190602001808311610b2d57829003601f168201915b505091505060006040518083038185876185025a03f1925050501515610b705760006000fd5b5b7fe3a3a4111a84df27d76b68dc721e65c7711605ea5eee4afd3a9c58195217365c338561010860008860001916600019168152602001908152602001600020600101546101086000896000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661010860008a6000191660001916815260200190815260200160002060020187604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186600019166000191681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610d475780601f10610d1c57610100808354040283529160200191610d47565b820191906000526020600020905b815481529060010190602001808311610d2a57829003601f168201915b505097505050505050505060405180910390a16101086000856000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160009055600282016000610db79190611be6565b505060019250610dc3565b5b5b5b5050919050565b600036604051808383808284378201915050925050506040518091039020610df381611678565b15610e0157816002819055505b5b5b5050565b60006000610e1333610659565b1561127357600084849050148015610e305750610e2f85611b51565b5b80610e3d57506001600054145b15610fed5760008673ffffffffffffffffffffffffffffffffffffffff161415610ea457610e9d8585858080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611b37565b9050610ef3565b8573ffffffffffffffffffffffffffffffffffffffff168585856040518083838082843782019150509250505060006040518083038185876185025a03f1925050501515610ef25760006000fd5b5b7f9738cd1a8777c86b011f7b01d87d484217dc6ab5154a9d41eda5d14af8caf292338688878786604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281038252858582818152602001925080828437820191505097505050505050505060405180910390a1611271565b6000364360405180848480828437820191505082815260200193505050506040518091039020915060006101086000846000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015611099575060006101086000846000191660001916815260200190815260200160002060010154145b80156110d85750600061010860008460001916600019168152602001908152602001600020600201805460018160011615610100020316600290049050145b1561118f57856101086000846000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550846101086000846000191660001916815260200190815260200160002060010181905550838361010860008560001916600019168152602001908152602001600020600201919061118d929190611c2e565b505b6111988261082f565b1515611270577f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328233878988886040518087600019166000191681526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b5b5b5b5b50949350505050565b60006000600061010560003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054925060008314156112be5761138c565b8260020a9150610106600085600019166000191681526020019081526020016000209050600082826001015416111561138b5780600001600081548092919060010191905055508181600101600082825403925050819055507fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b3385604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182600019166000191681526020019250505060405180910390a15b5b50505050565b6000366040518083838082843782019150509250505060405180910390206113b981611678565b15611415576001548211156113cd57611414565b816000819055506113dc611890565b7facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da826040518082815260200191505060405180910390a15b5b5b5050565b600060006000600061010660008760001916600019168152602001908152602001600020925061010560008673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561147f5760009350611493565b8160020a9050600081846001015416141593505b50505092915050565b6000600560018301610100811015156114b157fe5b0160005b505490505b919050565b60006000366040518083838082843782019150509250505060405180910390206114e881611678565b1561166b576114f683610659565b156115005761166a565b61010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561153b5761166a565b611543611890565b8273ffffffffffffffffffffffffffffffffffffffff166005836101008110151561156a57fe5b0160005b5081905550600061010560008673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508161010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15b5b5b50505050565b60025481565b600060006000600061010560003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054925060008314156116bb57611888565b6101066000866000191660001916815260200190815260200160002091506000826000015414156117455760005482600001819055506000826001018190555061010780548091906001016117109190611cae565b826002018190555084610107836002015481548110151561172d57fe5b906000526020600020900160005b5081600019169055505b8260020a90506000818360010154161415611887577fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda3386604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182600019166000191681526020019250505060405180910390a16001826000015411151561185e57610107610106600087600019166000191681526020019081526020016000206002015481548110151561180a57fe5b906000526020600020900160005b5060009055610106600086600019166000191681526020019081526020016000206000600082016000905560018201600090556002820160009055505060019350611888565b8160000160008154809291906001900391905055508082600101600082825417925050819055505b5b5b505050919050565b60006000610107805490509150600090505b818110156119bc576101086000610107838154811015156118bf57fe5b906000526020600020900160005b50546000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018201600090556002820160006119269190611be6565b505060006001026101078281548110151561193d57fe5b906000526020600020900160005b5054600019161415156119b05761010660006101078381548110151561196d57fe5b906000526020600020900160005b505460001916600019168152602001908152602001600020600060008201600090556001820160009055600282016000905550505b5b8060010190506118a2565b61010760006119cb9190611cda565b5b5050565b6000600190505b600154811015611b33575b60015481108015611a095750600060058261010081101515611a0057fe5b0160005b505414155b15611a1b5780806001019150506119e2565b5b6001600154118015611a4557506000600560015461010081101515611a3d57fe5b0160005b5054145b15611a625760016000815480929190600190039190505550611a1c565b60015481108015611a8b57506000600560015461010081101515611a8257fe5b0160005b505414155b8015611aac5750600060058261010081101515611aa457fe5b0160005b5054145b15611b2e57600560015461010081101515611ac357fe5b0160005b505460058261010081101515611ad957fe5b0160005b508190555080610105600060058461010081101515611af857fe5b0160005b50548152602001908152602001600020819055506000600560015461010081101515611b2457fe5b0160005b50819055505b6119d7565b5b50565b600081516020830184f09050803b15610000575b92915050565b6000611b5c33610659565b15611bc957600454611b6c611bcf565b1115611b89576000600381905550611b82611bcf565b6004819055505b600354826003540110158015611ba55750600254826003540111155b15611bc3578160036000828254019250508190555060019050611bc8565b600090505b5b5b919050565b60006201518042811515611bdf57fe5b0490505b90565b50805460018160011615610100020316600290046000825580601f10611c0c5750611c2b565b601f016020900490600052602060002090810190611c2a9190611cfc565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c6f57803560ff1916838001178555611c9d565b82800160010185558215611c9d579182015b82811115611c9c578235825591602001919060010190611c81565b5b509050611caa9190611cfc565b5090565b815481835581811511611cd557818360005260206000209182019101611cd49190611d21565b5b505050565b5080546000825590600052602060002090810190611cf89190611d21565b5b50565b611d1e91905b80821115611d1a576000816000905550600101611d02565b5090565b90565b611d4391905b80821115611d3f576000816000905550600101611d27565b5090565b90565b60006001541115611d575760006000fd5b611d6081611d71565b611d6a8383611d9c565b5b5b505050565b60006001541115611d825760006000fd5b80600281905550611d91611bcf565b6004819055505b5b50565b600060006001541115611daf5760006000fd5b600082111515611dbf5760006000fd5b81835110151515611dd05760006000fd5b8251600181905550600090505b8251811015611e85578281815181101515611df457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1660058260010161010081101515611e2757fe5b0160005b50819055508060010161010560008584815181101515611e4757fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b806001019050611ddd565b816000819055505b5b5050505600a165627a7a7230582016889f0740f073d397f9d00b0d19900fb050b957e3e2942f861085beb9baab180029", + "opcodes": "PUSH1 0x60 PUSH1 0x40 MSTORE CALLVALUE ISZERO PUSH3 0xD JUMPI INVALID JUMPDEST JUMPDEST PUSH1 0x0 DUP1 DUP1 SLOAD DUP1 PUSH1 0x1 ADD DUP3 DUP2 PUSH3 0x25 SWAP2 SWAP1 PUSH3 0x2D9 JUMP JUMPDEST SWAP2 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST PUSH1 0x0 SWAP1 SWAP2 SWAP1 SWAP2 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP POP PUSH3 0x120 DUP2 DUP1 SLOAD DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD DUP1 ISZERO PUSH3 0xFD JUMPI PUSH1 0x20 MUL DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 ADD SWAP1 DUP1 DUP4 GT PUSH3 0xB2 JUMPI JUMPDEST POP POP POP POP POP PUSH1 0x1 PUSH1 0x0 PUSH3 0x128 PUSH5 0x100000000 MUL PUSH3 0x1D46 OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST JUMPDEST POP PUSH3 0x330 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH3 0x13A JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH3 0x159 DUP2 PUSH3 0x180 PUSH5 0x100000000 MUL PUSH3 0x1D71 OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST PUSH3 0x179 DUP4 DUP4 PUSH3 0x1C2 PUSH5 0x100000000 MUL PUSH3 0x1D9C OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH3 0x192 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP1 PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x1B7 PUSH3 0x2C1 PUSH5 0x100000000 MUL PUSH3 0x1BCF OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST PUSH1 0x4 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH3 0x1D6 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH1 0x0 DUP3 GT ISZERO ISZERO PUSH3 0x1E7 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP2 DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH3 0x1F9 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP3 MLOAD PUSH1 0x1 DUP2 SWAP1 SSTORE POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP3 MLOAD DUP2 LT ISZERO PUSH3 0x2B3 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0x21F JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 DUP3 PUSH1 0x1 ADD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH3 0x253 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x1 ADD PUSH2 0x105 PUSH1 0x0 DUP6 DUP5 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0x274 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP JUMPDEST DUP1 PUSH1 0x1 ADD SWAP1 POP PUSH3 0x206 JUMP JUMPDEST DUP2 PUSH1 0x0 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH3 0x15180 TIMESTAMP DUP2 ISZERO ISZERO PUSH3 0x2D2 JUMPI INVALID JUMPDEST DIV SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 ISZERO GT PUSH3 0x303 JUMPI DUP2 DUP4 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP2 DUP3 ADD SWAP2 ADD PUSH3 0x302 SWAP2 SWAP1 PUSH3 0x308 JUMP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH3 0x32D SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x329 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x30F JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x1EBF DUP1 PUSH3 0x340 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x60 PUSH1 0x40 MSTORE CALLDATASIZE ISZERO PUSH2 0xEF JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x173825D9 EQ PUSH2 0x16D JUMPI DUP1 PUSH4 0x2F54BF6E EQ PUSH2 0x1A3 JUMPI DUP1 PUSH4 0x4123CB6B EQ PUSH2 0x1F1 JUMPI DUP1 PUSH4 0x52375093 EQ PUSH2 0x217 JUMPI DUP1 PUSH4 0x5C52C2F5 EQ PUSH2 0x23D JUMPI DUP1 PUSH4 0x659010E7 EQ PUSH2 0x24F JUMPI DUP1 PUSH4 0x7065CB48 EQ PUSH2 0x275 JUMPI DUP1 PUSH4 0x746C9171 EQ PUSH2 0x2AB JUMPI DUP1 PUSH4 0x797AF627 EQ PUSH2 0x2D1 JUMPI DUP1 PUSH4 0xB20D30A9 EQ PUSH2 0x30D JUMPI DUP1 PUSH4 0xB61D27F6 EQ PUSH2 0x32D JUMPI DUP1 PUSH4 0xB75C7DC6 EQ PUSH2 0x39C JUMPI DUP1 PUSH4 0xBA51A6DF EQ PUSH2 0x3C0 JUMPI DUP1 PUSH4 0xC2CF7326 EQ PUSH2 0x3E0 JUMPI DUP1 PUSH4 0xC41A360A EQ PUSH2 0x43B JUMPI DUP1 PUSH4 0xF00D4B5D EQ PUSH2 0x49B JUMPI DUP1 PUSH4 0xF1736D86 EQ PUSH2 0x4F0 JUMPI JUMPDEST PUSH2 0x16B JUMPDEST PUSH1 0x0 CALLVALUE GT ISZERO PUSH2 0x168 JUMPI PUSH32 0xE1FFFCC4923D04B559F4D29A8BFC6CDA04EB5B0D3C460751C2402C5C5CC9109C CALLER CALLVALUE PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x175 JUMPI INVALID JUMPDEST PUSH2 0x1A1 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x516 JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x1AB JUMPI INVALID JUMPDEST PUSH2 0x1D7 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x659 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x1F9 JUMPI INVALID JUMPDEST PUSH2 0x201 PUSH2 0x691 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x21F JUMPI INVALID JUMPDEST PUSH2 0x227 PUSH2 0x697 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x245 JUMPI INVALID JUMPDEST PUSH2 0x24D PUSH2 0x69D JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x257 JUMPI INVALID JUMPDEST PUSH2 0x25F PUSH2 0x6D7 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x27D JUMPI INVALID JUMPDEST PUSH2 0x2A9 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x6DD JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x2B3 JUMPI INVALID JUMPDEST PUSH2 0x2BB PUSH2 0x829 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x2D9 JUMPI INVALID JUMPDEST PUSH2 0x2F3 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x82F JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x315 JUMPI INVALID JUMPDEST PUSH2 0x32B PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0xDCC JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x335 JUMPI INVALID JUMPDEST PUSH2 0x37E PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP3 ADD DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP2 SWAP1 SWAP2 SWAP3 SWAP1 POP POP PUSH2 0xE06 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x3A4 JUMPI INVALID JUMPDEST PUSH2 0x3BE PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x127D JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x3C8 JUMPI INVALID JUMPDEST PUSH2 0x3DE PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x1392 JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x3E8 JUMPI INVALID JUMPDEST PUSH2 0x421 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x141A JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x443 JUMPI INVALID JUMPDEST PUSH2 0x459 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x149C JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x4A3 JUMPI INVALID JUMPDEST PUSH2 0x4EE PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x14BF JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x4F8 JUMPI INVALID JUMPDEST PUSH2 0x500 PUSH2 0x1672 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x53F DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x653 JUMPI PUSH2 0x105 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP2 POP PUSH1 0x0 DUP3 EQ ISZERO PUSH2 0x57F JUMPI PUSH2 0x652 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 SLOAD SUB PUSH1 0x0 SLOAD GT ISZERO PUSH2 0x593 JUMPI PUSH2 0x652 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 DUP4 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x5A5 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH2 0x5E6 PUSH2 0x1890 JUMP JUMPDEST PUSH2 0x5EE PUSH2 0x19D0 JUMP JUMPDEST PUSH32 0x58619076ADF5BB0943D100EF88D52D7C3FD691B19D3A9071B555B651FBF418DA DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD GT SWAP1 POP JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x1 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x4 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x6C4 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x6D3 JUMPI PUSH1 0x0 PUSH1 0x3 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x3 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x704 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x824 JUMPI PUSH2 0x712 DUP3 PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x71C JUMPI PUSH2 0x823 JUMP JUMPDEST PUSH2 0x724 PUSH2 0x1890 JUMP JUMPDEST PUSH1 0xFA PUSH1 0x1 SLOAD LT ISZERO ISZERO PUSH2 0x739 JUMPI PUSH2 0x738 PUSH2 0x19D0 JUMP JUMPDEST JUMPDEST PUSH1 0xFA PUSH1 0x1 SLOAD LT ISZERO ISZERO PUSH2 0x74A JUMPI PUSH2 0x823 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 ADD SWAP2 SWAP1 POP SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x785 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP PUSH1 0x1 SLOAD PUSH2 0x105 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH32 0x994A936646FE87FFE4F1E469D3D6AA417D6B855598397F323DE5B449F765F0C3 DUP3 PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 DUP3 PUSH2 0x83D DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0xDC4 JUMPI PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO DUP1 PUSH2 0x8C7 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD EQ ISZERO JUMPDEST DUP1 PUSH2 0x906 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 POP EQ ISZERO JUMPDEST ISZERO PUSH2 0xDC2 JUMPI PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA50 JUMPI PUSH2 0xA49 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD PUSH2 0x108 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xA3F JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xA14 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xA3F JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xA22 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP PUSH2 0x1B37 JUMP JUMPDEST SWAP2 POP PUSH2 0xB71 JUMP JUMPDEST PUSH2 0x108 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD PUSH2 0x108 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xB4A JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xB1F JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xB4A JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xB2D JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 PUSH2 0x8502 GAS SUB CALL SWAP3 POP POP POP ISZERO ISZERO PUSH2 0xB70 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST JUMPDEST PUSH32 0xE3A3A4111A84DF27D76B68DC721E65C7711605EA5EEE4AFD3A9C58195217365C CALLER DUP6 PUSH2 0x108 PUSH1 0x0 DUP9 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD PUSH2 0x108 PUSH1 0x0 DUP10 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x108 PUSH1 0x0 DUP11 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP8 PUSH1 0x40 MLOAD DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD DUP6 DUP2 MSTORE PUSH1 0x20 ADD DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP2 DUP2 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xD47 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xD1C JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xD47 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xD2A JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP8 POP POP POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 PUSH2 0x108 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD SWAP1 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 PUSH2 0xDB7 SWAP2 SWAP1 PUSH2 0x1BE6 JUMP JUMPDEST POP POP PUSH1 0x1 SWAP3 POP PUSH2 0xDC3 JUMP JUMPDEST JUMPDEST JUMPDEST JUMPDEST POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0xDF3 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0xE01 JUMPI DUP2 PUSH1 0x2 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH2 0xE13 CALLER PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x1273 JUMPI PUSH1 0x0 DUP5 DUP5 SWAP1 POP EQ DUP1 ISZERO PUSH2 0xE30 JUMPI POP PUSH2 0xE2F DUP6 PUSH2 0x1B51 JUMP JUMPDEST JUMPDEST DUP1 PUSH2 0xE3D JUMPI POP PUSH1 0x1 PUSH1 0x0 SLOAD EQ JUMPDEST ISZERO PUSH2 0xFED JUMPI PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xEA4 JUMPI PUSH2 0xE9D DUP6 DUP6 DUP6 DUP1 DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP4 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP POP POP POP POP PUSH2 0x1B37 JUMP JUMPDEST SWAP1 POP PUSH2 0xEF3 JUMP JUMPDEST DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 DUP6 DUP6 PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 PUSH2 0x8502 GAS SUB CALL SWAP3 POP POP POP ISZERO ISZERO PUSH2 0xEF2 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST JUMPDEST PUSH32 0x9738CD1A8777C86B011F7B01D87D484217DC6AB5154A9D41EDA5D14AF8CAF292 CALLER DUP7 DUP9 DUP8 DUP8 DUP7 PUSH1 0x40 MLOAD DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP7 DUP2 MSTORE PUSH1 0x20 ADD DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP6 DUP6 DUP3 DUP2 DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP8 POP POP POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 PUSH2 0x1271 JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE NUMBER PUSH1 0x40 MLOAD DUP1 DUP5 DUP5 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP4 POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 SWAP2 POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ DUP1 ISZERO PUSH2 0x1099 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD EQ JUMPDEST DUP1 ISZERO PUSH2 0x10D8 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 POP EQ JUMPDEST ISZERO PUSH2 0x118F JUMPI DUP6 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP DUP5 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD DUP2 SWAP1 SSTORE POP DUP4 DUP4 PUSH2 0x108 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD SWAP2 SWAP1 PUSH2 0x118D SWAP3 SWAP2 SWAP1 PUSH2 0x1C2E JUMP JUMPDEST POP JUMPDEST PUSH2 0x1198 DUP3 PUSH2 0x82F JUMP JUMPDEST ISZERO ISZERO PUSH2 0x1270 JUMPI PUSH32 0x1733CBB53659D713B79580F79F3F9FF215F78A7C7AA45890F3B89FC5CDDFBF32 DUP3 CALLER DUP8 DUP10 DUP9 DUP9 PUSH1 0x40 MLOAD DUP1 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP6 DUP2 MSTORE PUSH1 0x20 ADD DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP5 DUP3 DUP2 DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP8 POP POP POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST JUMPDEST JUMPDEST POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP3 POP PUSH1 0x0 DUP4 EQ ISZERO PUSH2 0x12BE JUMPI PUSH2 0x138C JUMP JUMPDEST DUP3 PUSH1 0x2 EXP SWAP2 POP PUSH2 0x106 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SWAP1 POP PUSH1 0x0 DUP3 DUP3 PUSH1 0x1 ADD SLOAD AND GT ISZERO PUSH2 0x138B JUMPI DUP1 PUSH1 0x0 ADD PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 ADD SWAP2 SWAP1 POP SSTORE POP DUP2 DUP2 PUSH1 0x1 ADD PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH32 0xC7FB647E59B18047309AA15AAD418E5D7CA96D173AD704F1031A2C3D7591734B CALLER DUP6 PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x13B9 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x1415 JUMPI PUSH1 0x1 SLOAD DUP3 GT ISZERO PUSH2 0x13CD JUMPI PUSH2 0x1414 JUMP JUMPDEST DUP2 PUSH1 0x0 DUP2 SWAP1 SSTORE POP PUSH2 0x13DC PUSH2 0x1890 JUMP JUMPDEST PUSH32 0xACBDB084C721332AC59F9B8E392196C9EB0E4932862DA8EB9BEAF0DAD4F550DA DUP3 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH2 0x106 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SWAP3 POP PUSH2 0x105 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP2 POP PUSH1 0x0 DUP3 EQ ISZERO PUSH2 0x147F JUMPI PUSH1 0x0 SWAP4 POP PUSH2 0x1493 JUMP JUMPDEST DUP2 PUSH1 0x2 EXP SWAP1 POP PUSH1 0x0 DUP2 DUP5 PUSH1 0x1 ADD SLOAD AND EQ ISZERO SWAP4 POP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 DUP4 ADD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x14B1 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD SWAP1 POP JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x14E8 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x166B JUMPI PUSH2 0x14F6 DUP4 PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x1500 JUMPI PUSH2 0x166A JUMP JUMPDEST PUSH2 0x105 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP2 POP PUSH1 0x0 DUP3 EQ ISZERO PUSH2 0x153B JUMPI PUSH2 0x166A JUMP JUMPDEST PUSH2 0x1543 PUSH2 0x1890 JUMP JUMPDEST DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 DUP4 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x156A JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP DUP2 PUSH2 0x105 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH32 0xB532073B38C83145E3E5135377A08BF9AAB55BC0FD7C1179CD4FB995D2A5159C DUP5 DUP5 PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x2 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP3 POP PUSH1 0x0 DUP4 EQ ISZERO PUSH2 0x16BB JUMPI PUSH2 0x1888 JUMP JUMPDEST PUSH2 0x106 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SWAP2 POP PUSH1 0x0 DUP3 PUSH1 0x0 ADD SLOAD EQ ISZERO PUSH2 0x1745 JUMPI PUSH1 0x0 SLOAD DUP3 PUSH1 0x0 ADD DUP2 SWAP1 SSTORE POP PUSH1 0x0 DUP3 PUSH1 0x1 ADD DUP2 SWAP1 SSTORE POP PUSH2 0x107 DUP1 SLOAD DUP1 SWAP2 SWAP1 PUSH1 0x1 ADD PUSH2 0x1710 SWAP2 SWAP1 PUSH2 0x1CAE JUMP JUMPDEST DUP3 PUSH1 0x2 ADD DUP2 SWAP1 SSTORE POP DUP5 PUSH2 0x107 DUP4 PUSH1 0x2 ADD SLOAD DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x172D JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP DUP2 PUSH1 0x0 NOT AND SWAP1 SSTORE POP JUMPDEST DUP3 PUSH1 0x2 EXP SWAP1 POP PUSH1 0x0 DUP2 DUP4 PUSH1 0x1 ADD SLOAD AND EQ ISZERO PUSH2 0x1887 JUMPI PUSH32 0xE1C52DC63B719ADE82E8BEA94CC41A0D5D28E4AAF536ADB5E9CCCC9FF8C1AEDA CALLER DUP7 PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 PUSH1 0x1 DUP3 PUSH1 0x0 ADD SLOAD GT ISZERO ISZERO PUSH2 0x185E JUMPI PUSH2 0x107 PUSH2 0x106 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD SLOAD DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x180A JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP PUSH1 0x0 SWAP1 SSTORE PUSH2 0x106 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE POP POP PUSH1 0x1 SWAP4 POP PUSH2 0x1888 JUMP JUMPDEST DUP2 PUSH1 0x0 ADD PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 SWAP1 SUB SWAP2 SWAP1 POP SSTORE POP DUP1 DUP3 PUSH1 0x1 ADD PUSH1 0x0 DUP3 DUP3 SLOAD OR SWAP3 POP POP DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH2 0x107 DUP1 SLOAD SWAP1 POP SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP2 DUP2 LT ISZERO PUSH2 0x19BC JUMPI PUSH2 0x108 PUSH1 0x0 PUSH2 0x107 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x18BF JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD SWAP1 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 PUSH2 0x1926 SWAP2 SWAP1 PUSH2 0x1BE6 JUMP JUMPDEST POP POP PUSH1 0x0 PUSH1 0x1 MUL PUSH2 0x107 DUP3 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x193D JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x0 NOT AND EQ ISZERO ISZERO PUSH2 0x19B0 JUMPI PUSH2 0x106 PUSH1 0x0 PUSH2 0x107 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x196D JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE POP POP JUMPDEST JUMPDEST DUP1 PUSH1 0x1 ADD SWAP1 POP PUSH2 0x18A2 JUMP JUMPDEST PUSH2 0x107 PUSH1 0x0 PUSH2 0x19CB SWAP2 SWAP1 PUSH2 0x1CDA JUMP JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SWAP1 POP JUMPDEST PUSH1 0x1 SLOAD DUP2 LT ISZERO PUSH2 0x1B33 JUMPI JUMPDEST PUSH1 0x1 SLOAD DUP2 LT DUP1 ISZERO PUSH2 0x1A09 JUMPI POP PUSH1 0x0 PUSH1 0x5 DUP3 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1A00 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ ISZERO JUMPDEST ISZERO PUSH2 0x1A1B JUMPI DUP1 DUP1 PUSH1 0x1 ADD SWAP2 POP POP PUSH2 0x19E2 JUMP JUMPDEST JUMPDEST PUSH1 0x1 PUSH1 0x1 SLOAD GT DUP1 ISZERO PUSH2 0x1A45 JUMPI POP PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1A3D JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ JUMPDEST ISZERO PUSH2 0x1A62 JUMPI PUSH1 0x1 PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 SWAP1 SUB SWAP2 SWAP1 POP SSTORE POP PUSH2 0x1A1C JUMP JUMPDEST PUSH1 0x1 SLOAD DUP2 LT DUP1 ISZERO PUSH2 0x1A8B JUMPI POP PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1A82 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ ISZERO JUMPDEST DUP1 ISZERO PUSH2 0x1AAC JUMPI POP PUSH1 0x0 PUSH1 0x5 DUP3 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AA4 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ JUMPDEST ISZERO PUSH2 0x1B2E JUMPI PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AC3 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x5 DUP3 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AD9 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP DUP1 PUSH2 0x105 PUSH1 0x0 PUSH1 0x5 DUP5 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AF8 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1B24 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP JUMPDEST PUSH2 0x19D7 JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD PUSH1 0x20 DUP4 ADD DUP5 CREATE SWAP1 POP DUP1 EXTCODESIZE ISZERO PUSH2 0x0 JUMPI JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1B5C CALLER PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x1BC9 JUMPI PUSH1 0x4 SLOAD PUSH2 0x1B6C PUSH2 0x1BCF JUMP JUMPDEST GT ISZERO PUSH2 0x1B89 JUMPI PUSH1 0x0 PUSH1 0x3 DUP2 SWAP1 SSTORE POP PUSH2 0x1B82 PUSH2 0x1BCF JUMP JUMPDEST PUSH1 0x4 DUP2 SWAP1 SSTORE POP JUMPDEST PUSH1 0x3 SLOAD DUP3 PUSH1 0x3 SLOAD ADD LT ISZERO DUP1 ISZERO PUSH2 0x1BA5 JUMPI POP PUSH1 0x2 SLOAD DUP3 PUSH1 0x3 SLOAD ADD GT ISZERO JUMPDEST ISZERO PUSH2 0x1BC3 JUMPI DUP2 PUSH1 0x3 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH1 0x1 SWAP1 POP PUSH2 0x1BC8 JUMP JUMPDEST PUSH1 0x0 SWAP1 POP JUMPDEST JUMPDEST JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH3 0x15180 TIMESTAMP DUP2 ISZERO ISZERO PUSH2 0x1BDF JUMPI INVALID JUMPDEST DIV SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST POP DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV PUSH1 0x0 DUP3 SSTORE DUP1 PUSH1 0x1F LT PUSH2 0x1C0C JUMPI POP PUSH2 0x1C2B JUMP JUMPDEST PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1C2A SWAP2 SWAP1 PUSH2 0x1CFC JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH2 0x1C6F JUMPI DUP1 CALLDATALOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH2 0x1C9D JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH2 0x1C9D JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH2 0x1C9C JUMPI DUP3 CALLDATALOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH2 0x1C81 JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH2 0x1CAA SWAP2 SWAP1 PUSH2 0x1CFC JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 ISZERO GT PUSH2 0x1CD5 JUMPI DUP2 DUP4 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0x1CD4 SWAP2 SWAP1 PUSH2 0x1D21 JUMP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST POP DUP1 SLOAD PUSH1 0x0 DUP3 SSTORE SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1CF8 SWAP2 SWAP1 PUSH2 0x1D21 JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH2 0x1D1E SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1D1A JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH2 0x1D02 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x1D43 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1D3F JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH2 0x1D27 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH2 0x1D57 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH2 0x1D60 DUP2 PUSH2 0x1D71 JUMP JUMPDEST PUSH2 0x1D6A DUP4 DUP4 PUSH2 0x1D9C JUMP JUMPDEST JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH2 0x1D82 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP1 PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH2 0x1D91 PUSH2 0x1BCF JUMP JUMPDEST PUSH1 0x4 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH2 0x1DAF JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH1 0x0 DUP3 GT ISZERO ISZERO PUSH2 0x1DBF JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP2 DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0x1DD0 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP3 MLOAD PUSH1 0x1 DUP2 SWAP1 SSTORE POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP3 MLOAD DUP2 LT ISZERO PUSH2 0x1E85 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1DF4 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 DUP3 PUSH1 0x1 ADD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1E27 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x1 ADD PUSH2 0x105 PUSH1 0x0 DUP6 DUP5 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1E47 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP JUMPDEST DUP1 PUSH1 0x1 ADD SWAP1 POP PUSH2 0x1DDD JUMP JUMPDEST DUP2 PUSH1 0x0 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP POP POP JUMP STOP LOG1 PUSH6 0x627A7A723058 SHA3 AND DUP9 SWAP16 SMOD BLOCKHASH CREATE PUSH20 0xD397F9D00B0D19900FB050B957E3E2942F861085 0xbe 0xb9 0xba 0xab XOR STOP 0x29 ", + "sourceMap": "2715:10853:0:-;;;3523:112;;;;;;;3552:18;3574:8;:27;;;;;;;;;;;:::i;:::-;;;;;;;;;;;3596:3;3574:27;;;;;;;;;;;;;;;;;;;;;;;3605:26;3616:8;3605:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3626:1;3629;3605:10;;;;;:26;;;:::i;:::-;3523:112;;2715:10853;;7697:168;7585:1;7571:11;;:15;7567:26;;;7588:5;;;7567:26;7800:23;7813:9;7800:12;;;;;:23;;;:::i;:::-;7827:34;7842:7;7851:9;7827:14;;;;;:34;;;:::i;:::-;7595:1;7697:168;;;;:::o;6966:115::-;7585:1;7571:11;;:15;7567:26;;;7588:5;;;7567:26;7048:6;7033:12;:21;;;;7070:7;:5;;;;;:7;;;:::i;:::-;7058:9;:19;;;;7595:1;6966:115;;:::o;3977:349::-;4171:6;7585:1;7571:11;;:15;7567:26;;;7588:5;;;7567:26;4088:1;4076:9;:13;4068:22;;;;;;;;4120:9;4102:7;:14;:27;;4094:36;;;;;;;;4148:7;:14;4134:11;:28;;;;4180:1;4171:10;;4166:131;4187:7;:14;4183:1;:18;4166:131;;;4238:7;4246:1;4238:10;;;;;;;;;;;;;;;;;;4233:16;;4215:8;4228:1;4224;:5;4215:15;;;;;;;;;;;;:34;;;;;4291:1;4287;:5;4254:12;:30;4272:7;4280:1;4272:10;;;;;;;;;;;;;;;;;;4267:16;;4254:30;;;;;;;;;;;:38;;;;4166:131;4203:3;;;;;4166:131;;;4313:9;4300:10;:22;;;;7595:1;3977:349;;;;:::o;12529:73::-;12572:4;12593:6;12587:3;:12;;;;;;;;12580:19;;12529:73;;:::o;2715:10853::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;", + "linkReferences": {} } ``` @@ -85,13 +85,13 @@ At `CNSTNTNPL_FORK_BLKNUM`, directly recreate the account ``` * Storage: - * `0x0000000000000000000000000000000000000000000000000000000000000000`: + * `0x0000000000000000000000000000000000000000000000000000000000000000`: `0x0000000000000000000000000000000000000000000000000000000000000001` - * `0x0000000000000000000000000000000000000000000000000000000000000001`: + * `0x0000000000000000000000000000000000000000000000000000000000000001`: `0x0000000000000000000000000000000000000000000000000000000000000001` - * `0x0000000000000000000000000000000000000000000000000000000000000004`: + * `0x0000000000000000000000000000000000000000000000000000000000000004`: `0x00000000000000000000000000000000000000000000000000000000000044e1` - * `0xa5baec7d73105a3c7298203bb205bbc41b63fa384ae73a6016b890a7ca29ae2d`: + * `0xa5baec7d73105a3c7298203bb205bbc41b63fa384ae73a6016b890a7ca29ae2d`: `0x0000000000000000000000000000000000000000000000000000000000000001` The balance of the account shall be left unchanged. @@ -102,13 +102,13 @@ At `CNSTNTNPL_FORK_BLKNUM`, directly recreate the account * Nonce: `0x1` * Storage: - * `0x0000000000000000000000000000000000000000000000000000000000000000`: + * `0x0000000000000000000000000000000000000000000000000000000000000000`: `0x0000000000000000000000000000000000000000000000000000000000000001` - * `0x0000000000000000000000000000000000000000000000000000000000000001`: + * `0x0000000000000000000000000000000000000000000000000000000000000001`: `0x0000000000000000000000000000000000000000000000000000000000000001` - * `0x0000000000000000000000000000000000000000000000000000000000000004`: + * `0x0000000000000000000000000000000000000000000000000000000000000004`: `0x00000000000000000000000000000000000000000000000000000000000044e1` - * `0xa5baec7d73105a3c7298203bb205bbc41b63fa384ae73a6016b890a7ca29ae2d`: + * `0xa5baec7d73105a3c7298203bb205bbc41b63fa384ae73a6016b890a7ca29ae2d`: `0x0000000000000000000000000000000000000000000000000000000000000001` In addition, the codehash at that address shall be replaced by the codehash at diff --git a/Gemfile b/Gemfile index c8f707f6f832e..97d520e604db0 100644 --- a/Gemfile +++ b/Gemfile @@ -31,4 +31,4 @@ gem "wdm", "~> 0.1.0" if Gem.win_platform? gem "html-proofer", '>=3.3.1' -gem "eip_validator", ">=0.8.0" +gem "eip_validator", ">=0.8.2" diff --git a/Gemfile.lock b/Gemfile.lock index bc94a2e3c348a..6082d6b3b3b79 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,7 +21,7 @@ GEM commonmarker (0.17.9) ruby-enum (~> 0.5) concurrent-ruby (1.0.5) - eip_validator (0.8.0) + eip_validator (0.8.2) activemodel front_matter_parser (~> 0.1.1) ethon (0.11.0) @@ -257,7 +257,7 @@ PLATFORMS ruby DEPENDENCIES - eip_validator (>= 0.8.0) + eip_validator (>= 0.8.2) github-pages html-proofer (>= 3.3.1) jekyll (~> 3.6.2) diff --git a/README.md b/README.md index c313bcde2265c..b8d85fa74a4c2 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ A browsable version of all current and draft EIPs can be found on [the official Your first PR should be a first draft of the final EIP. It must meet the formatting criteria enforced by the build (largely, correct metadata in the header). An editor will manually review the first PR for a new EIP and assign it a number before merging it. Make sure you include a `discussions-to` header with the URL to a discussion forum or open GitHub issue where people can discuss the EIP as a whole. -If your EIP requires images, the image files should be included in a subdirectory of the `assets` folder for that EIP as follow: `assets/eip-X` (for eip **X**). When linking to an image in the EIP, use relative links such as `../assets/eip-X/image.png`. +If your EIP requires images, the image files should be included in a subdirectory of the `assets` folder for that EIP as follows: `assets/eip-X` (for eip **X**). When linking to an image in the EIP, use relative links such as `../assets/eip-X/image.png`. Once your first PR is merged, we have a bot that helps out by automatically merging PRs to draft EIPs. For this to work, it has to be able to tell that you own the draft being edited. Make sure that the 'author' line of your EIP contains either your Github username or your email address inside . If you use your email address, that address must be the one publicly shown on [your GitHub profile](https://github.com/settings/profile). @@ -22,13 +22,28 @@ When you believe your EIP is mature and ready to progress past the draft phase, - **For all other EIPs**, open a PR changing the state of your EIP to 'Final'. An editor will review your draft and ask if anyone objects to its being finalised. If the editor decides there is no rough consensus - for instance, because contributors point out significant issues with the EIP - they may close the PR and request that you fix the issues in the draft before trying again. # EIP Status Terms + * **Draft** - an EIP that is undergoing rapid iteration and changes. * **Last Call** - an EIP that is done with its initial iteration and ready for review by a wide audience. -* **Accepted** - a core EIP that has been in Last Call for at least 2 weeks and any technical changes that were requested have been addressed by the author. The process for Core Devs to decide whether to encode an EIP into their clients as part of a hard fork is not part of the EIP process. If such a decision is made, the EIP wil move to final. +* **Accepted** - a core EIP that has been in Last Call for at least 2 weeks and any technical changes that were requested have been addressed by the author. The process for Core Devs to decide whether to encode an EIP into their clients as part of a hard fork is not part of the EIP process. If such a decision is made, the EIP will move to final. * **Final (non-Core)** - an EIP that has been in Last Call for at least 2 weeks and any technical changes that were requested have been addressed by the author. * **Final (Core)** - an EIP that the Core Devs have decided to implement and release in a future hard fork or has already been released in a hard fork. * **Deferred** - an EIP that is not being considered for immediate adoption. May be reconsidered in the future for a subsequent hard fork. # Preferred Citation Format -The canonical URL for a EIP that has achieved draft status at any point is at https://eips.ethereum.org/. For example, the canonical URL for ERC-165 is https://eips.ethereum.org/EIPS/eip-165. +The canonical URL for a EIP that has achieved draft status at any point is at https://eips.ethereum.org/. For example, the canonical URL for EIP-1 is https://eips.ethereum.org/EIPS/eip-1. + +# Validation + +EIPs must pass some validation tests. The EIP repository ensures this by running tests using [html-proofer](https://rubygems.org/gems/html-proofer) and [eip_validator](https://rubygems.org/gems/eip_validator). + +It is possible to run the EIP validator locally: +``` +gem install eip_validator +eip_validator +``` + +# Automerger + +The EIP repository contains an "auto merge" feature to ease the workload for EIP editors. If a change is made via a PR to a draft EIP, then the authors of the EIP can Github approve the change to have it auto-merged by the [eip-automerger](https://github.com/eip-automerger/automerger) bot. diff --git a/_config.yml b/_config.yml index d6c9410dd030d..b0fbe061bb2fc 100644 --- a/_config.yml +++ b/_config.yml @@ -27,8 +27,8 @@ header_pages: - networking.html - interface.html - erc.html - - informational.html - meta.html + - informational.html twitter: card: summary username: ethereum diff --git a/_data/statuses.yaml b/_data/statuses.yaml index 469095233884d..c6644865db1f6 100644 --- a/_data/statuses.yaml +++ b/_data/statuses.yaml @@ -3,5 +3,7 @@ - Accepted - Final - Active +- Abandoned - Deferred +- Rejected - Superseded diff --git a/assets/eip-1057/test-vectors-0.9.2.json b/assets/eip-1057/test-vectors-0.9.2.json new file mode 100644 index 0000000000000..b10408ae736ac --- /dev/null +++ b/assets/eip-1057/test-vectors-0.9.2.json @@ -0,0 +1,107 @@ +[ + { + "block_height": 30000, + "nonce": "123456789abcdef0", + "header_hash": "ffeeddccbbaa9988776655443322110000112233445566778899aabbccddeeff", + "mix_hash": "11f19805c58ab46610ff9c719dcf0a5f18fa2f1605798eef770c47219274767d", + "final_hash": "5b7ccd472dbefdd95b895cac8ece67ff0deb5a6bd2ecc6e162383d00c3728ece" + }, + { + "block_height": 0, + "nonce": "0000000000000000", + "header_hash": "0000000000000000000000000000000000000000000000000000000000000000", + "mix_hash": "faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3", + "final_hash": "63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b" + }, + { + "block_height": 49, + "nonce": "0000000006ff2c47", + "header_hash": "63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b", + "mix_hash": "c789c1180f890ec555ff42042913465481e8e6bc512cb981e1c1108dc3f2227d", + "final_hash": "9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922" + }, + { + "block_height": 50, + "nonce": "00000000076e482e", + "header_hash": "9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922", + "mix_hash": "c7340542c2a06b3a7dc7222635f7cd402abf8b528ae971ddac6bbe2b0c7cb518", + "final_hash": "de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d" + }, + { + "block_height": 99, + "nonce": "000000003917afab", + "header_hash": "de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d", + "mix_hash": "f5e60b2c5bfddd136167a30cbc3c8dbdbd15a512257dee7964e0bc6daa9f8ba7", + "final_hash": "ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce" + }, + { + "block_height": 29950, + "nonce": "005d409dbc23a62a", + "header_hash": "ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce", + "mix_hash": "07393d15805eb08ee6fc6cb3ad4ad1010533bd0ff92d6006850246829f18fd6e", + "final_hash": "e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5" + }, + { + "block_height": 29999, + "nonce": "005db5fa4c2a3d03", + "header_hash": "e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5", + "mix_hash": "7551bddf977491da2f6cfc1679299544b23483e8f8ee0931c4c16a796558a0b8", + "final_hash": "d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454" + }, + { + "block_height": 30000, + "nonce": "005db8607994ff30", + "header_hash": "d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454", + "mix_hash": "f1c2c7c32266af9635462e6ce1c98ebe4e7e3ecab7a38aaabfbf2e731e0fbff4", + "final_hash": "8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64" + }, + { + "block_height": 30049, + "nonce": "005e2e215a8ca2e7", + "header_hash": "8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64", + "mix_hash": "57fe6a9fbf920b4e91deeb66cb0efa971e08229d1a160330e08da54af0689add", + "final_hash": "c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047" + }, + { + "block_height": 30050, + "nonce": "005e30899481055e", + "header_hash": "c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047", + "mix_hash": "ba30c61cc5a2c74a5ecaf505965140a08f24a296d687e78720f0b48baf712f2d", + "final_hash": "ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71" + }, + { + "block_height": 30099, + "nonce": "005ea6aef136f88b", + "header_hash": "ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71", + "mix_hash": "cfd5e46048cd133d40f261fe8704e51d3f497fc14203ac6a9ef6a0841780b1cd", + "final_hash": "49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6" + }, + { + "block_height": 59950, + "nonce": "02ebe0503bd7b1da", + "header_hash": "49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6", + "mix_hash": "21511fbaa31fb9f5fc4998a754e97b3083a866f4de86fa7500a633346f56d773", + "final_hash": "f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf" + }, + { + "block_height": 59999, + "nonce": "02edb6275bd221e3", + "header_hash": "f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf", + "mix_hash": "653eda37d337e39d311d22be9bbd3458d3abee4e643bee4a7280a6d08106ef98", + "final_hash": "341562d10d4afb706ec2c8d5537cb0c810de02b4ebb0a0eea5ae335af6fb2e88" + }, + { + "block_height": 10000000, + "nonce": "005e30899481055e", + "header_hash": "efda178de857b2b1703d8d5403bd0f848e19cff5c50ba5c0d6210ddb16250ec3", + "mix_hash": "b2403f56c426177856eaf0eedd707c86ae78a432b9169c3689a67058fcf2a848", + "final_hash": "206aee640c0fd21473d5cc3654d63c80442d9e2dfa676d2801d3ec1fbab38a6d" + }, + { + "block_height": 100000000, + "nonce": "02abe0589481055e", + "header_hash": "49e15ba4bf501ce8fe88765403bd0f848e19cff5c50ba5c0d6210ddb16250ec3", + "mix_hash": "ac452084d6f4e6eacf4282ad58dbd4ce7ef2653fb5e6b5c877f56928c907432a", + "final_hash": "b879f84923e71b812ef5a42ece0b5b9366c31cab218f40afe65f8a2cae448a6f" + } +] diff --git a/assets/eip-1057/test-vectors-0.9.3.json b/assets/eip-1057/test-vectors-0.9.3.json new file mode 100644 index 0000000000000..054c3dadb4498 --- /dev/null +++ b/assets/eip-1057/test-vectors-0.9.3.json @@ -0,0 +1,108 @@ +[ + { + "block_height": 30000, + "nonce": "123456789abcdef0", + "header_hash": "ffeeddccbbaa9988776655443322110000112233445566778899aabbccddeeff", + "mix_hash": "6018c151b0f9895ebe44a4ca6ce2829e5ba6ae1a68a4ccd05a67ac01219655c1", + "final_hash": "34d8436444aa5c61761ce0bcce0f11401df2eace77f5c14ba7039b86b5800c08" + }, + { + "block_height": 0, + "nonce": "0000000000000000", + "header_hash": "0000000000000000000000000000000000000000000000000000000000000000", + "mix_hash": "f4ac202715ded4136e72887c39e63a4738331c57fd9eb79f6ec421c281aa8743", + "final_hash": "b3bad9ca6f7c566cf0377d1f8cce29d6516a96562c122d924626281ec948ef02" + }, + { + "block_height": 49, + "nonce": "0000000006ff2c47", + "header_hash": "63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b", + "mix_hash": "8f744dec9140938453c8a502a489861aedec7e98ce7e11b10a3b661940c38786", + "final_hash": "ca0c365f1290ede4ee0d19cab08cd827030425ae8aba96b5248faafe732f1f80" + }, + { + "block_height": 50, + "nonce": "00000000076e482e", + "header_hash": "9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922", + "mix_hash": "bd772e573609acead3b0f27d7935022ea0bf72f22ecf0980f0c21a74cc2fa3ef", + "final_hash": "75439f6c6e153d3c798309f01ba37e7a284d172f50841c7b523e81c1b8247083" + }, + { + "block_height": 99, + "nonce": "000000003917afab", + "header_hash": "de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d", + "mix_hash": "18a5d2f1eaa3df5a54f254c3f90bfa8e40c63913664175c93a9e5136f4dc7c5c", + "final_hash": "2618185c024ad29fd75bc350da388cc0d47cdebbd6798400f17692a7ccf3314c" + }, + { + "block_height": 29950, + "nonce": "005d409dbc23a62a", + "header_hash": "ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce", + "mix_hash": "d98cd262f73f9e110d994e592ad793ffca5fa92d8aff0e6f40fe3e84940e09e5", + "final_hash": "8ec8a0486e759c59c6f7ba586450dc2a5c8c3586b52345efb9b604fa82f40f65" + }, + { + "block_height": 29999, + "nonce": "005db5fa4c2a3d03", + "header_hash": "e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5", + "mix_hash": "53979a1e55d7b1987664570920a3d9121052f06326b99c6698b38255ed419003", + "final_hash": "de03c1354159e07cf804ecc9a53f82b0187dd4a24837d20e56cae28b65c35eb0" + }, + { + "block_height": 30000, + "nonce": "005db8607994ff30", + "header_hash": "d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454", + "mix_hash": "ec3eed8a744b1950ae72439e8d28a47b868f4cdc26e5c37084e441cceb289c21", + "final_hash": "a717a28081999625860cbb09262dbbcc6090427411a5a3c60fb86a0ded8d369e" + }, + { + "block_height": 30049, + "nonce": "005e2e215a8ca2e7", + "header_hash": "8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64", + "mix_hash": "ed3764d1cf0abc3798c594a372679dd076f7dda15b552e7ec83d3ba8b27cbe0c", + "final_hash": "dd85d293db9b1063c6428ac9ca74e8d5d4d9fee49e0123bafb914fa787f58e89" + }, + { + "block_height": 30050, + "nonce": "005e30899481055e", + "header_hash": "c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047", + "mix_hash": "732a4c5f7de1cc6d2a3702e9ea717b4f9da0de66e75897a2d5dc6cf407e883fc", + "final_hash": "4e83a686a5390b8105a261c4c1480b23a17938d4d029d1239042be7515e980fa" + }, + { + "block_height": 30099, + "nonce": "005ea6aef136f88b", + "header_hash": "ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71", + "mix_hash": "be8789da582670b3b5091d3693b7584b5a554cd258c9a3f299645cfaf13acff9", + "final_hash": "72a6b01403faf90b2e74cb28920e953016d2c04f3e22d64aa4712ed00b5b6681" + }, + { + "block_height": 59950, + "nonce": "02ebe0503bd7b1da", + "header_hash": "49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6", + "mix_hash": "3d1093e05b7ac6f23bda5afecf36f01379f05df06a28bcefd3459b70941bbc41", + "final_hash": "56c9fefbfe93eac6de18b1bd4e42d6bf784f9dc5a112955d2ffa6d5fb3cc0657" + }, + { + "block_height": 59999, + "nonce": "02edb6275bd221e3", + "header_hash": "f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf", + "mix_hash": "855c62aba873a0955345556f2ba33cb1d74b7d42067402e6ec145dd031087b23", + "final_hash": "116053ccb7866e23df4263a359794fa84afceb0d11d97cb9389ffa763b7be43a" + }, + { + "block_height": 10000000, + "nonce": "005e30899481055e", + "header_hash": "efda178de857b2b1703d8d5403bd0f848e19cff5c50ba5c0d6210ddb16250ec3", + "mix_hash": "3cb394b257046429e7a18528f2d1bc64e3b712031534ecb1f60f5c6d61fd60ca", + "final_hash": "5dca7eab5997b489420b5d05d56394b8be83824bcb5916b84d8b39d54186a6d6" + }, + { + "block_height": 100000000, + "nonce": "02abe0589481055e", + "header_hash": "49e15ba4bf501ce8fe88765403bd0f848e19cff5c50ba5c0d6210ddb16250ec3", + "mix_hash": "cc8a24ce78d5df7787f7b47bad87c7ef5d4e159ba5d32d5d6b01a6c5c4a2b536", + "final_hash": "eba819f45d27b39cc0a8deb68b6dde03c37a9790634eeb6a1d0edb40ed26ee1d" + } +] + diff --git a/assets/eip-1057/test-vectors.md b/assets/eip-1057/test-vectors.md index a47c7e89d2b1b..5fcec000ab513 100644 --- a/assets/eip-1057/test-vectors.md +++ b/assets/eip-1057/test-vectors.md @@ -1,6 +1,6 @@ # Test Vectors for EIP-1057 - ProgPow -Many of these vectors are dervived from [chfast/ethash](https://github.com/chfast/ethash) +Many of these vectors are derived from [chfast/ethash](https://github.com/chfast/ethash) ## fnv1a @@ -121,7 +121,7 @@ Kiss 99 state: For the first loop iteration of block 30,000 the seed to use for `fill_mix` would be `0xEE304846DDD0A47B`. A two dimensional `mix` array should be created -passing the rows into `fill_mix` witht he column number as the loop argument. +passing the rows into `fill_mix` with the column number as the loop argument. The state of the mix array after the call to `progPowLoop` for block 30,000, loop 1 are as follows. @@ -336,122 +336,128 @@ loop 1 are as follows. ## progPowHash +### 0.9.2 +[Machine-readable data](https://github.com/ethereum/EIPs/blob/ad4e73f239d53d72a21cfd8fdc89dc81eb9d2688/assets/eip-1057/test-vectors-0.9.3.json) + Block 30000: - `prog_seed` - 600 - `nonce` - `123456789abcdef0` - `header` - `ffeeddccbbaa9988776655443322110000112233445566778899aabbccddeeff` -- _digest_ - `11f19805c58ab46610ff9c719dcf0a5f18fa2f1605798eef770c47219274767d` -- _result_ - `5b7ccd472dbefdd95b895cac8ece67ff0deb5a6bd2ecc6e162383d00c3728ece` +- `mix_hash` - `11f19805c58ab46610ff9c719dcf0a5f18fa2f1605798eef770c47219274767d` +- `final_hash` - `5b7ccd472dbefdd95b895cac8ece67ff0deb5a6bd2ecc6e162383d00c3728ece` Block 0: - `prog_seed` - 0 - `nonce` - `0000000000000000` - `header` - `0000000000000000000000000000000000000000000000000000000000000000` -- _digest_ - `faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3` -- _result_ - `63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12` +- `mix_hash` - `faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3` +- `final_hash` - `63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b` Block 49: - `prog_seed` - 0 - `nonce` - `0000000006ff2c47` - `header` - `63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b` -- _digest_ - `c789c1180f890ec555ff42042913465481e8e6bc512cb981e1c1108dc3f2227d` -- _result_ - `9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd92` +- `mix_hash` - `c789c1180f890ec555ff42042913465481e8e6bc512cb981e1c1108dc3f2227d` +- `final_hash` - `9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922` Block 50: - `prog_seed` - 1 - `nonce` - `00000000076e482e` - `header` - `9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922` -- _digest_ - `c7340542c2a06b3a7dc7222635f7cd402abf8b528ae971ddac6bbe2b0c7cb518` -- _result_ - `de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188` +- `mix_hash` - `c7340542c2a06b3a7dc7222635f7cd402abf8b528ae971ddac6bbe2b0c7cb518` +- `final_hash` - `de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d` Block 99: - `prog_seed` - 1 - `nonce` - `000000003917afab` - `header` - `de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d` -- _digest_ - `f5e60b2c5bfddd136167a30cbc3c8dbdbd15a512257dee7964e0bc6daa9f8ba7` -- _result_ - `ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcc` +- `mix_hash` - `f5e60b2c5bfddd136167a30cbc3c8dbdbd15a512257dee7964e0bc6daa9f8ba7` +- `final_hash` - `ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce` Block 29,950: - `prog_seed` - 599 - `nonce` - `005d409dbc23a62a` - `header` - `ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce` -- _digest_ - `07393d15805eb08ee6fc6cb3ad4ad1010533bd0ff92d6006850246829f18fd6e` -- _result_ - `e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f` +- `mix_hash` - `07393d15805eb08ee6fc6cb3ad4ad1010533bd0ff92d6006850246829f18fd6e` +- `final_hash` - `e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5` Block 29,999: - `prog_seed` - 599 - `nonce` - `005db5fa4c2a3d03` - `header` - `e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5` -- _digest_ - `7551bddf977491da2f6cfc1679299544b23483e8f8ee0931c4c16a796558a0b8` -- _result_ - `d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c645` +- `mix_hash` - `7551bddf977491da2f6cfc1679299544b23483e8f8ee0931c4c16a796558a0b8` +- `final_hash` - `d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454` Block 30,000: - `prog_seed` - 600 - `nonce` - `005db8607994ff30` - `header` - `d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454` -- _digest_ - `f1c2c7c32266af9635462e6ce1c98ebe4e7e3ecab7a38aaabfbf2e731e0fbff4` -- _result_ - `8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef6` +- `mix_hash` - `f1c2c7c32266af9635462e6ce1c98ebe4e7e3ecab7a38aaabfbf2e731e0fbff4` +- `final_hash` - `8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64` Block 30,049: - `prog_seed` - 600 - `nonce` - `005e2e215a8ca2e7` - `header` - `8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64` -- _digest_ - `57fe6a9fbf920b4e91deeb66cb0efa971e08229d1a160330e08da54af0689add` -- _result_ - `c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe0904` +- `mix_hash` - `57fe6a9fbf920b4e91deeb66cb0efa971e08229d1a160330e08da54af0689add` +- `final_hash` - `c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047` Block 30,050: - `prog_seed` - 601 - `nonce` - `005e30899481055e` - `header` - `c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047` -- _digest_ - `ba30c61cc5a2c74a5ecaf505965140a08f24a296d687e78720f0b48baf712f2d` -- _result_ - `ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc7` +- `mix_hash` - `ba30c61cc5a2c74a5ecaf505965140a08f24a296d687e78720f0b48baf712f2d` +- `final_hash` - `ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71` Block 30,099: - `prog_seed` - 601 - `nonce` - `005ea6aef136f88b` - `header` - `ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71` -- _digest_ - `cfd5e46048cd133d40f261fe8704e51d3f497fc14203ac6a9ef6a0841780b1cd` -- _result_ - `49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd` +- `mix_hash` - `cfd5e46048cd133d40f261fe8704e51d3f497fc14203ac6a9ef6a0841780b1cd` +- `final_hash` - `49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6` Block 59,950: - `prog_seed` - 1,199 - `nonce` - `02ebe0503bd7b1da` - `header` - `49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6` -- _digest_ - `21511fbaa31fb9f5fc4998a754e97b3083a866f4de86fa7500a633346f56d773` -- _result_ - `f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19c` +- `mix_hash` - `21511fbaa31fb9f5fc4998a754e97b3083a866f4de86fa7500a633346f56d773` +- `final_hash` - `f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf` Block 59,999: - `prog_seed` - 1,199 - `nonce` - `02edb6275bd221e3` - `header` - `f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf` -- _digest_ - `653eda37d337e39d311d22be9bbd3458d3abee4e643bee4a7280a6d08106ef98` -- _result_ - `341562d10d4afb706ec2c8d5537cb0c810de02b4ebb0a0eea5ae335af6fb2e8` +- `mix_hash` - `653eda37d337e39d311d22be9bbd3458d3abee4e643bee4a7280a6d08106ef98` +- `final_hash` - `341562d10d4afb706ec2c8d5537cb0c810de02b4ebb0a0eea5ae335af6fb2e88` Block 10,000,000: - `prog_seed` - 200,000 - `nonce` - `005e30899481055e` - `header` - `efda178de857b2b1703d8d5403bd0f848e19cff5c50ba5c0d6210ddb16250ec3` -- _digest_ - `b2403f56c426177856eaf0eedd707c86ae78a432b9169c3689a67058fcf2a848` -- _result_ - `206aee640c0fd21473d5cc3654d63c80442d9e2dfa676d2801d3ec1fbab38a6d` +- `mix_hash` - `b2403f56c426177856eaf0eedd707c86ae78a432b9169c3689a67058fcf2a848` +- `final_hash` - `206aee640c0fd21473d5cc3654d63c80442d9e2dfa676d2801d3ec1fbab38a6d` Block 100,000,000: - `prog_seed` - 2,000,000 - `nonce` - `02abe0589481055e` - `header` - `49e15ba4bf501ce8fe88765403bd0f848e19cff5c50ba5c0d6210ddb16250ec3` -- _digest_ - `ac452084d6f4e6eacf4282ad58dbd4ce7ef2653fb5e6b5c877f56928c907432a` -- _result_ - `b879f84923e71b812ef5a42ece0b5b9366c31cab218f40afe65f8a2cae448a6f` \ No newline at end of file +- `mix_hash` - `ac452084d6f4e6eacf4282ad58dbd4ce7ef2653fb5e6b5c877f56928c907432a` +- `final_hash` - `b879f84923e71b812ef5a42ece0b5b9366c31cab218f40afe65f8a2cae448a6f` + +### 0.9.3 +[Machine-readable data](https://github.com/ethereum/EIPs/blob/ad4e73f239d53d72a21cfd8fdc89dc81eb9d2688/assets/eip-1057/test-vectors-0.9.3.json) diff --git a/assets/eip-1901/OpenRPC_structure.png b/assets/eip-1901/OpenRPC_structure.png new file mode 100644 index 0000000000000..412bb8a4a0ac7 Binary files /dev/null and b/assets/eip-1901/OpenRPC_structure.png differ diff --git a/assets/eip-1901/multi-geth-use-case.png b/assets/eip-1901/multi-geth-use-case.png new file mode 100644 index 0000000000000..08f5db4eb11f9 Binary files /dev/null and b/assets/eip-1901/multi-geth-use-case.png differ diff --git a/assets/eip-747/add-token-prompt.gif b/assets/eip-747/add-token-prompt.gif new file mode 100644 index 0000000000000..6d8549807a645 Binary files /dev/null and b/assets/eip-747/add-token-prompt.gif differ diff --git a/assets/eip-747/add-token-prompt2.gif b/assets/eip-747/add-token-prompt2.gif new file mode 100644 index 0000000000000..cf7cb7c56b94e Binary files /dev/null and b/assets/eip-747/add-token-prompt2.gif differ diff --git a/eip-X.md b/eip-X.md index e1c1c80b22920..66dd31b69e70f 100644 --- a/eip-X.md +++ b/eip-X.md @@ -4,7 +4,7 @@ title: author: , FirstName (@GitHubUsername) and GitHubUsername (@GitHubUsername)> discussions-to: status: Draft -type: +type: category (*only required for Standard Track): created: requires (*optional): diff --git a/index.html b/index.html index 079dd0922d5c8..507775cb35acf 100644 --- a/index.html +++ b/index.html @@ -16,7 +16,7 @@

EIP status terms