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

BEP-228: Implement EIP-3541: Prevent deploying contracts starting with 0xEF #228

Merged
merged 2 commits into from
May 25, 2023

Conversation

Mister-EA
Copy link
Contributor

@Mister-EA Mister-EA commented Apr 17, 2023

    BEP: 228
    Title: Prevent deploying contracts starting with 0xEF
    Status: Pre-Draft
    Type: Standards
    Created: 2023-04-17

BEP-228: Prevent deploying contracts starting with 0xEF.

1. Summary

Disallow new code starting with the 0xEF byte to be deployed. Code already existing in the account trie starting with 0xEF byte is not affected semantically by this change.

This BEP essentially enables Ethereum's EIP-3541. The code has been already ported from go-ethereum. What remains is for this BEP to be enabled in a BSC hard fork.

2. Motivation

Contracts conforming to the EVM Object Format (EOF) are going to be validated at deploy time. In order to guarantee that every EOF-formatted contract in the state is valid, we need to prevent already deployed (and not validated) contracts from being recognized as such format. This will be achieved by choosing a byte sequence for the magic that doesn't exist in any of the already deployed contracts. To prevent the growth of the search space and to limit the analysis to the contracts existing before this fork, we disallow the starting byte of the format (the first byte of the magic).

Should the EVM Object Format proposal not be deployed in the future, the magic can be used by other features depending on versioning. In the case versioning becomes obsolete, it is simple to roll this back by allowing contracts starting with the 0xEF byte to be deployed again.

3. Specification

After block.number == HF_BLOCK new contract creation (via create transaction, CREATE or CREATE2 instructions) results in an exceptional abort if the code's first byte is 0xEF.

3.1 Remarks

The initcode is the code executed in the context of the create transaction, CREATE, or CREATE2 instructions. The initcode returns code (via the RETURN instruction), which is inserted into the account. See section 7 ("Contract Creation") in the Yellow Paper for more information.

The opcode 0xEF is currently an undefined instruction, therefore: It pops no stack items and pushes no stack items, and it causes an exceptional abort when executed. This means initcode or already deployed code starting with this instruction will continue to abort execution.

The exceptional abort due to code starting with 0xEF behaves exactly the same as any other exceptional abort that can occur during initcode execution, i.e. in case of abort all gas provided to a CREATE* or create transaction is consumed.

4. Rationale

The 0xEF byte was chosen because it resembles Executable Format.

Contracts using unassigned opcodes are generally understood to be at risk of changing semantics. Hence using the unassigned 0xEF should have lesser effects, than choosing an assigned opcode, such as 0xFD (REVERT), 0xFE (INVALID), or 0xFF (SELFDESTRUCT). Arguably while such contracts may not be very useful, they are still using valid opcodes.

Analysis in May 2021, on 18084433 contracts in state, showed that there are 0 existing contracts starting with the 0xEF byte, as opposed to 1, 4, and 12 starting with 0xFD, 0xFE, and 0xFF, respectively.

5. Test Cases

Each test case below may be executed in 3 different contexts:

  • create transaction (no account code)
  • CREATE, with account code: 0x6000356000523660006000f0151560165760006000fd5b (Yul code: mstore(0, calldataload(0)) if iszero(create(0, 0, calldatasize())) { revert(0, 0) }),
  • CREATE2, with account code: 0x60003560005260003660006000f5151560185760006000fd5b (Yul code: mstore(0, calldataload(0)) if iszero(create2(0, 0, calldatasize(), 0)) { revert(0, 0) })
Case Calldata Expected result
deploy one byte ef 0x60ef60005360016000f3 new contract not deployed, transaction fails
deploy two bytes ef00 0x60ef60005360026000f3 new contract not deployed, transaction fails
deploy three bytes ef0000 0x60ef60005360036000f3 new contract not deployed, transaction fails
deploy 32 bytes ef00...00 0x60ef60005360206000f3 new contract not deployed, transaction fails
deploy one byte fe 0x60fe60005360016000f3 new contract deployed, transaction succeeds

6. Backwards Compatibility

This is a breaking change given new code starting with the 0xEF byte will not be deployable, and contract creation will result in a failure. However, given bytecode is executed starting at its first byte, code deployed with 0xEF as the first byte is not executable anyway.

While this means no currently executable contract is affected, it does rejects deployment of new data contracts starting with the 0xEF byte.

7. Security Considerations

The authors are not aware of any security or DoS risks posed by this change.

8. License

Copyright and related rights waived via CC0.

@Mister-EA Mister-EA marked this pull request as ready for review April 17, 2023 11:02
@jacksonbinh4
Copy link

#127

@Mister-EA Mister-EA changed the title BEP-228: Prevent deploying contracts starting with 0xEF BEP-228: Implement EIP-3541: Prevent deploying contracts starting with 0xEF May 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants