Appearance
Simple Summary
Provide a standardized format for Ethereum Recovery Proposals (ERPs), which relate to recovery of certain classes of lost funds. Individual ERPs will follow the same process as any EIP, but will be formatted and evaluated in a standard way to ensure consistency and transparency.
This EIP does not advocate for or against the acceptance of any particular recovery proposals, nor would its acceptance alone result in any state changes to the blockchain.
Abstract
This proposal identifies a common solution method that can be used to address certain classes of lost funds on the Ethereum blockchain. In particular, it is intended to address cases where there is no disagreement about the right outcome between directly affected parties, enabling timely and low-risk solutions to many issues that have already occurred or are likely to occur again as Ethereum grows.
The solution method is divided into three parts:
- Standards that will need to be met by any follow-on ERP in order to be considered for approval.
- Recommendations for a common format for ERPs to use to specify a set of corrective actions that can be interpreted by clients.
- Guidelines for client teams to implement code that can read, interpret, and apply the corrective actions at a specific block. The set of possible corrective actions is intentionally limited to minimize risk associated with any ERP.
Motivation
The issue of fund recovery on the Ethereum blockchain is often controversial. Frozen fund recovery proposals are almost never successful due to the relatively ad-hoc nature of such requests and the subjectivity that is often required to evaluate the merits. This EIP attempts to remove these barriers by providing both a standardized format for fund recovery EIPs and an objective standard by which to measure future proposals.
Specification
This EIP describes a common format to be used for a subclass of EIPs, referred to as ethereum recovery proposals (ERPs), that propose an irregular state change required to address a fund recovery scenario that cannot be addressed using the standard protocol. Each ERP will reference this EIP will follow the guidelines set out here.
The purpose of each ERP is (a) to clearly describe the issue to be corrected, (b) to describe why an irregular state change is both necessary and justified, and (c) to demonstrate that the proposed actions will achieve the ERP's objectives.
Each ERP will be required to use a standard format to represent the set of proposed state changes and must include a verification script that can reliably generate those changes. ERPs that do not meet (at least) these requirements will not be considered for approval.
Each ERP should contain the following items:
- Preamble: EIP (RFC 822) header containing metadata about the ERP, including the EIP number, a short title (44 character maximum), and the real names (and optional contact information) for each author.
- Simple Summary: A simplified and layman-accessible explanation of the ERP.
- Detailed description: A human-readable description of the proposed corrective actions and the criteria used to determine the proposed actions.
- Justification: A concise description of why the corrective actions are both reasonable and unlikely to be challenged by any directly affected party.
- Verification script: A machine-readable script that outputs one State Change Object. The script should clearly implement the selection and action generating logic outlined in the description such that reviewers can independently re-generate an identical State Change Object.
- State Change Object: The output of the verification script and the input to the ethereum clients. Primarily, it specifies the complete set of proposed state change actions.
- Appendix (optional): with supporting evidence. Attachments in the appendix may include documents verifying details specified as part of the recovery proposal description.
The following sections give more detailed descriptions of the expectations for the Justification, Verification Script, and the format of the State Change Object.
Justification
A concise description of why this action is both reasonable (cannot be accomplished without an irregular state change) and unlikely to be challenged by a directly affected party.
Considerable example (concise, includes supporting evidence, no negative impact): A crowdsale run by XYZ incorrectly published the testnet address of their crowdsale contract to their public website at the start of their crowdsale on Jan 19, 2018. 501 ETH was sent by 328 users on the mainnet to the incorrect address between block 4,235,987 and 4,236,050. See here for the testnet contract, and see here for the transactions to the same address on the mainnet. See here for a statement made by XYZ on their website. Because there is a contract at this address on the testnet and the corresponding nonce for the creator address has already been used on the mainnet, it is considered effectively impossible that anyone coincidentally holds the private key. We have verified that all transactions came from addresses with no associated code, so there should be no issue returning eth to the senders.
Insufficient example (not enough detail, no supporting evidence): We accidentally put the wrong contract address up on our website. Can you please refund any eth sent to 0x1234 back to the senders. Thanks.
Unacceptable example (not objective, one person’s word against another): I sent tokens to X for services and he did a lousy job. I want my money back, but he won’t refund me. Please help!!
Verification Script
A machine-readable script that outputs a single State Change Object. This script should be implemented so that it is easily audited by a reviewer. Verification scripts should be javascript files that may use the web3.js library.
There are a few guidelines for verification scripts:
- Scripts should always be written to be as concise as reasonably possible, and anyone executing the verification script should review it first to verify that it does not contain any unsafe operations.
- No verification script should ever require an unlocked ethereum wallet
- The script should hardcode the highest block included during execution (otherwise the results may differ between runs).
The purpose of the ERP Verification script is to unambiguously specify (through code) the criteria used to compute the set of State Change Actions. The script’s output, as described above, will be the input used by all Ethereum clients. Client teams should avoid manually pre-processing the artifact or using the artifact to simply guide changes in the code. Instead, the artifact should be bundled with the client and processed directly by the client at the specified block. This will minimize the amount of client effort required for each ERP and help to ensure compatibility between clients. We anticipate that some ERP Verification scripts may be trivial, but we recommend their inclusion for consistency.
State Change Object
The State Change Object is a standard format that will be interpretable by all Ethereum clients.
It is a single JSON object containing the following fields:
- erpId: A string identifier for this ERP (likely the associated EIP number, e.g. “EIP-1234”). This will be converted from ascii to a hex string, then added as extra data on the target block.
- targetBlock: The block at which the stateChange should be applied. Clients would use this to determine when a set of state changes should occur
- actions: An array of State Change Actions.
- metadata
- sourceBlock: The highest block considered by the script when it was run.
- version: The version of the verification script when it was run.
State Change Actions
A State Change action is a JSON object that includes a “type” field and a set of “data” fields, where the contents of the data fields are dependent on the type and must follow the schema defined for that type. This allows clients to support a limited set of operations initially and add more based on a subsequent EIP if needed. Support for the following action types should be implemented by clients upon adoption of this EIP:
weiTransfer
The weiTransfer
action transfers ETH from one address to another.
Data fields
- type (string):
weiTransfer
- fromAddress (hex string): The address from which ETH should be transferred
- toAddress (hex string): The address to which ETH should be sent
- value (decimal string): The amount of ETH to be transferred, in units of wei. The value must be a whole number greater than zero.
storeCode
The storeCode
action stores the given code at the given address.
Data fields
- type (string):
storeCode
- toAddress (hex string): The address to which the contract should be restored.
- expectedCodeHash (hex string): the expected hash of the code already at the toAddress.The empty string should be used if no code is expected at the toAddress. In all other cases, the “0x” prefix is optional.
- code (hex string): the new bytecode associated with the contract
Appendix (Optional)
The appendix can include additional supporting evidence or attachments that will help reviewers understand or verify the claims made in the ERP.
For the storeCode operation, it should include the proposed contract source (e.g. Solidity) as well as the other details required such that a reviewer can compile the source and generate the same bytecode. It should also include the source that was originally stored at that address, if possible/applicable. If the two contracts are not identical, changes should be noted. If they are identical, the author should indicate why no changes are necessary (this is unlikely). Additionally, any relevant reviews, audits, and test cases should be included to the extent that they address the issues encountered with the original contract.
If accepted, an ERP could easily compile the block at while the changes are to take place, and the source of the actions (which would be the output of the script, in a standardized object output). These can be bundled with the client for seamless execution.
ERP Approval Process
ERPs are a subclass of EIPs and will, therefore, follow the same approval process.
Testing
The ERP authors are currently seeking feedback from client teams about the proper testing procedures
Ethereum Client Implementation
Clients that choose to adopt the proposal outlined in this EIP will implement a module that scans a designated directory for SCO files (each time the client process launches) to construct a mapping between target blocks and SCO file names. When starting work on a new block, clients should first consult the set of SCO target blocks discovered and determine if there are any recovery actions required for the current block.
E.g. in this example, erpsByTargetBlock
is the mapping between the target block number associated with each ERP's State Change Object and a reference (i.e. file name) to the resource with the actual data.
if (erpsByTargetBlock.get(currentBlock) != null) {
try {
applyRecoveryActions(erpsByTargetBlock.get(currentBlock));
}
catch (e) {
// recovery actions should be treated as a batch.
// If one fails, they all fail.
}
}
// continue with normal block processing...
The applyRecoveryActions
method must apply the recovery actions in the same order as they are stored in the SCO file. Clients are responsible for ensuring that no State Change Action will result in an account transferring an amount that is greater than its current balance. The toAddress
for both weiTransfer
and storeCode
should always be a valid address (i.e. never 0x0
).
Additionally, each block affected by an ERP should include extra data to indicate that the state change occurred. The extra data included in the block should be the erpId found in the SCO file, converted to hex (i.e. hexStringToBytes(asciiToHex(erpId))
). Clients should also validate that the expected header appears in the target block if the block is received from a peer.
The ERP should link to pull requests for each client repository, and these pull requests should link back to the ERP and also contain its EIP preamble and summary.
Each PR associated with an ERP should consist of a single file (the SCO file) added to the client’s designated SCO directory. No additional client code should be required.
Limitations of this EIP
This EIP is focused on standardizing how recovery proposals can be formatted, to optimize readability and eliminate or minimize as much as possible the potential for mistakes or intentional abuses.
The following are considered out of scope from this EIP:
- Which fund recovery proposals, if any, should be accepted for implementation.
- How common classes of recovery proposal plaintiff may organize ERPs representing a collective group of individual parties
Rationale
The primary consideration for the approach described above was to minimize the amount of risk associated with recovery actions that would otherwise not have a viable solution. A secondary consideration was to standardize the format used in the proposals for recovery actions.
First, including a verification script guarantees that the way in which the recovery actions were determined is unambiguous. This does not mean that the recovery actions are necessarily correct, only that the logic used to determine them is fully specified and auditable.
Second, requiring that the output of the verification script is directly interpretable by client programs minimizes the work necessary for each client to adopt a particular ERP. It also reduces the risk that two clients will make different decisions about the implementation of a particular ERP.
Third, action types are intentionally limited and inflexible, which reduces the likelihood of unintended consequences or maliciously constructed files affecting the blockchain state. The format is easily extensible with new actions types if needed but that would require a separate EIP.
Implementation
A reference implementation has been written for the EthereumJ platform. See the pull request here.
ERP Examples
This section will include examples and SCO resource files, as well as a brief tutorial on how to test using a private testnet.
Copyright
Copyright and related rights waived via CC0.