Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update EIP-3860: Clarify nonce rules #6040

Merged
merged 3 commits into from
Nov 25, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 18 additions & 16 deletions EIPS/eip-3860.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ discussions-to: https://ethereum-magicians.org/t/eip-3860-limit-and-meter-initco
status: Review
type: Standards Track
category: Core
requires: 170
created: 2021-07-16
requires: 170
---

## Abstract
Expand All @@ -24,17 +24,19 @@ Lastly, the size limit results in the nice-to-have property that EVM code size,
During contract creation the client has to perform jumpdest-analysis on the `initcode` prior to execution. The work performed scales linearly with the size of the `initcode`. This work currently is not metered, nor is there a protocol enforced upper bound for the size.

There are three costs charged today:

1. Cost for calldata aka `initcode`: 4 gas for a byte with the value of zero, and 16 gas otherwise.
2. Cost for the resulting deployed code: 200 gas per byte.
3. Cost of address calculation (hashing of code) in case of `CREATE2` only: 6 gas per word.

Only the first cost applies to `initcode`, but only in the case of contract creation transactions. For the case of `CREATE`/`CREATE2` there is no such cost, and it is possible to programmatically generate variations of initcode in a relatively cheap manner. In the past it was possible to craft malicious `initcode` due to a vulnerability fixed in 2017 by [geth 1.6.5](https://github.com/ethereum/go-ethereum/releases/tag/v1.6.5).
Only the first cost applies to `initcode`, but only in the case of contract creation transactions. For the case of `CREATE`/`CREATE2` there is no such cost, and it is possible to programmatically generate variations of `initcode` in a relatively cheap manner. In the past it was possible to craft malicious `initcode` due to a vulnerability fixed in 2017 by geth 1.6.5.

Furthermore the lack of a limit has caused lengthy discussions for some EVM proposals, influencing the design, or even causing a delay or cancellation of a feature.
Furthermore, the lack of a limit has caused lengthy discussions for some EVM proposals, influencing the design, or even causing a delay or cancellation of a feature.

We are motivated by three reasons:

1. Ensuring `initcode` is fairly charged (most importantly cost is proportional to `initcode`'s length) to minimize the risks for the future.
2. To have a cost system which is extendable in the future (i.e. for proposals like EIP-3670).
2. To have a cost system which is extendable in the future (i.e. for proposals like [EIP-3670](./eip-3670.md)).
3. To simplify EVM engines by the explicit limits (code size, code offsets (`PC`), and jump offsets fit 16-bits).

## Specification
Expand All @@ -54,8 +56,8 @@ We define `initcode_cost(initcode)` to equal `INITCODE_WORD_COST * ceil(len(init

1. If length of transaction data (`initcode`) in a create transaction exceeds `MAX_INITCODE_SIZE`, transaction is invalid. (*Note that this is similar to transactions considered invalid for not meeting the intrinsic gas cost requirement.*)
2. For a create transaction, extend the transaction data cost formula to include `initcode_cost(initcode)`. (*Note that this is included in transaction intrinsic cost, i.e. transaction with not enough gas to cover initcode cost is invalid.*)
3. If length of `initcode` to `CREATE` or `CREATE2` instructions exceeds `MAX_INITCODE_SIZE`, instruction execution ends with the result `0` pushed on the stack. Gas for initcode execution is not deducted in this case.
4. For the `CREATE` and `CREATE2` instructions charge an extra gas cost equaling to `initcode_cost(initcode)`. This cost is deducted before the calculation of the resulting contract address and the execution of `initcode`. (*Note that this means before or at the same time as the hashing cost is applied in `CREATE2`.*)
3. If length of `initcode` to `CREATE` or `CREATE2` instructions exceeds `MAX_INITCODE_SIZE`, instruction execution ends with the result `0` pushed on the stack. Gas for initcode execution is not deducted and caller's nonce is not incremented in this case.
4. For the `CREATE` and `CREATE2` instructions charge an extra gas cost equaling to `initcode_cost(initcode)`. This cost is deducted before the calculation of the resulting contract address and the execution of `initcode`. (*Note that this means before or at the same time as the hashing cost is applied in `CREATE2`.*) If the instruction fails due to the `initcode` length check of point 3, this cost is not deducted.

## Rationale

Expand All @@ -74,7 +76,7 @@ The value of `INITCODE_WORD_COST` is selected based on performance benchmarks of

We have chosen the cost of 2 gas per word based on Geth's implementation and comparing with `KECCAK256` performance. This means the per byte cost is `0.0625`. While fractional gas costs are not permitted in the EVM, we can approximate it by charging per-word.

Moreover, calculating gas per word is compatible with the calculation of `CREATE2`'s _hashcost_ of [EIP-1014](./eip-1014.md). Therefore the same implementation may be used for `CREATE` and `CREATE2` with different cost constants: before activation `0` for `CREATE` and `6` for `CREATE2`, after activation `2` for `CREATE` and `6 + 2` for `CREATE2`.
Moreover, calculating gas per word is compatible with the calculation of `CREATE2`'s *hashcost* of [EIP-1014](./eip-1014.md). Therefore, the same implementation may be used for `CREATE` and `CREATE2` with different cost constants: before activation `0` for `CREATE` and `6` for `CREATE2`, after activation `2` for `CREATE` and `6 + 2` for `CREATE2`.

### Reason for size limit of initcode

Expand All @@ -92,22 +94,14 @@ The initcode cost for create transaction data (0.0625 gas per byte) is negligibl

### How to report initcode limit violation?

We specified that initcode size limit violation for `CREATE`/`CREATE2` results in `0` on stack. Most checks in these instructions are specified this way, with the exception of 3 checks not specific to creation instructions (stack underflow, out of gas, static call violation). In these three cases the entire execution is exceptionally aborted. However we decided to be consistent with the majority of the possible error conditions in order to keep the specification and implementations simple.
We specified that initcode size limit violation for `CREATE`/`CREATE2` results in `0` on stack. Most checks in these instructions are specified this way, except for 3 checks not specific to creation instructions (stack underflow, out of gas, static call violation). In these three cases the entire execution is exceptionally aborted. However, we decided to be consistent with the majority of the possible error conditions in order to keep the specification and implementations simple.

## Backwards Compatibility

This EIP requires a "network upgrade", since it modifies consensus rules.

Already deployed contracts should not be effected, but certain transactions (with `initcode` beyond the proposed limit) would still be includable in a block, but result in an exceptional abort.

## Security Considerations

For client implementations, this EIP makes attacks based on jumpdest-analysis less problematic, so should increase the robustness of clients.

For layer 2, this EIP introduces failure-modes where there previously were none. There _could_ exist factory-contracts which deploy multi-level contract hierarchies, such that the code for multiple contracts are included in the initcode of the first contract. The author(s) of this EIP are not aware of any such contracts.

Currently, on London, with `30M` gas limit, it would be possible to trigger jumpdest-analysis of a total `~1.3GB` of initcode. With this EIP, the cost for such an attack would increase by roughly `80M` gas.

## Test Cases

Tests should include the following cases:
Expand All @@ -117,6 +111,14 @@ Tests should include the following cases:
- `CREATE`/`CREATE2`/creation transaction with `len(initcode)` at `MAX_INITCODE_SIZE`
- `CREATE`/`CREATE2`/creation transaction with `len(initcode)` at `MAX_INITCODE_SIZE+1`

## Security Considerations

For client implementations, this EIP makes attacks based on jumpdest-analysis less problematic, so should increase the robustness of clients.

For layer 2, this EIP introduces failure-modes where there previously were none. There *could* exist factory-contracts which deploy multi-level contract hierarchies, such that the code for multiple contracts are included in the initcode of the first contract. The author(s) of this EIP are not aware of any such contracts.

Currently, on London, with `30M` gas limit, it would be possible to trigger jumpdest-analysis of a total `~1.3GB` of initcode. With this EIP, the cost for such an attack would increase by roughly `80M` gas.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).