Skip to content

Commit

Permalink
Merge pull request #16 from ethereum/master
Browse files Browse the repository at this point in the history
update
  • Loading branch information
wighawag authored May 24, 2019
2 parents f8a75d5 + dbf67d4 commit bfd5d86
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 8 deletions.
5 changes: 4 additions & 1 deletion EIPS/eip-107.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
eip: 107
title: safe "eth_sendTransaction" authorization via html popup
author: Ronan Sandford <wighawag@gmail.com>
author: Ronan Sandford (@wighawag)
created: 2016-06-05
status: Draft
type: Standards Track
Expand Down Expand Up @@ -612,3 +612,6 @@ That's it.
</body>
</html>
```
## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
15 changes: 8 additions & 7 deletions EIPS/eip-1155.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pragma solidity ^0.5.8;
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 (see "Safe Transfer Rules" section of the standard).
The `_operator` argument MUST be msg.sender.
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.
Expand All @@ -56,7 +56,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 (see "Safe Transfer Rules" section of the standard).
The `_operator` argument MUST be msg.sender.
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.
Expand Down Expand Up @@ -242,7 +242,8 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op
* 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 unexpectedly fails the transaction MUST be reverted.
* 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.

#### Rules

Expand All @@ -269,7 +270,7 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op
**_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 msg.sender.
- 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.
Expand All @@ -278,7 +279,7 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op
- When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
* `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 msg.sender.
- 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.
Expand All @@ -292,7 +293,7 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op
- 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 the account/contract that initiated the transfer (i.e. msg.sender).
- 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.
Expand All @@ -309,7 +310,7 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op
- The set of all calls to `onERC1155Received` and `onERC1155BatchReceived` describes all balance changes that occurred during the transaction in the order submitted.

**_onERC1155BatchReceived rules:_**
* The `_operator` argument MUST be the address of the account/contract that initiated the transfer (i.e. msg.sender).
- 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.
Expand Down
1 change: 1 addition & 0 deletions EIPS/eip-1679.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ This meta-EIP specifies the changes included in the Ethereum hardfork named Ista
- [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-1959](https://eips.ethereum.org/EIPS/eip-1959): New Opcode to check if a chainID is part of the history of chainIDs
- [EIP-2028](https://eips.ethereum.org/EIPS/eip-2028): Calldata gas cost reduction
- [EIP-2046](https://eips.ethereum.org/EIPS/eip-2046): Reduced gas cost for static calls made to precompiles

Expand Down
79 changes: 79 additions & 0 deletions EIPS/eip-1959.md
Original file line number Diff line number Diff line change
@@ -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/).

0 comments on commit bfd5d86

Please sign in to comment.