HackMD
    • Sharing Link copied
    • /edit
    • View mode
      • Edit mode
      • View mode
      • Book mode
      • Slide mode
      Edit mode View mode Book mode Slide mode
    • Note Permission
    • Read
      • Owners
      • Signed-in users
      • Everyone
      Owners Signed-in users Everyone
    • Write
      • Owners
      • Signed-in users
      • Everyone
      Owners Signed-in users Everyone
    • More (Comment, Invitee)
    • Publishing
    • Commenting Enable
      Disabled Forbidden Owners Signed-in users Everyone
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Invitee
    • No invitee
    • Options
    • Versions and GitHub Sync
    • Transfer ownership
    • Delete this note
    • Template
    • Insert from template
    • Export
    • Google Drive Export to Google Drive
    • Gist
    • Import
    • Google Drive Import from Google Drive
    • Gist
    • Clipboard
    • Download
    • Markdown
    • HTML
    • Raw HTML
Menu Sharing Help
Menu
Options
Versions and GitHub Sync Transfer ownership Delete this note
Export
Google Drive Export to Google Drive Gist
Import
Google Drive Import from Google Drive Gist Clipboard
Download
Markdown HTML Raw HTML
Back
Sharing
Sharing Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
More (Comment, Invitee)
Publishing
More (Comment, Invitee)
Commenting Enable
Disabled Forbidden Owners Signed-in users Everyone
Permission
Owners
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Invitee
No invitee
   owned this note    owned this note      
Published Linked with GitHub
Like BookmarkBookmarked
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
# EOFv2 Design Space ###### tags: `EOF` [toc] ## Summary We introduce completely new semantics for contract creation (in the context of EOF contracts). This results in legacy transaction types not being able to create EOF contracts, and a new transaction type only allowing EOF contract creation. This reduces complexity and costs. Furthermore we replace the `CREATE` and `CREATE2` instructions with `CREATE3`, which calculates addresses similar to `CREATE2`, but handles EOF containers opaquely. As a side effect, the `nonce` field in the account becomes inert in EOF accounts. This new design has three (beneficial) side-effects: 1. The concept of "data contracts" are not implementable in EOF context. We think this is a good feature. (It could be enabled with introducing `EXTDATACOPY`,.. instructions.) 2. ~~Initcode can use `REVERT`/`RETURN` to communicate information, but do not control what is being deployed.~~ 3. Create transactions can be used (in a limited capacity) similarly to ["rich transactions"](https://ethereum-magicians.org/t/rich-transactions-via-evm-bytecode-execution-from-externally-owned-accounts/4025). The difference is they do not impersonate the caller address. ## Container Add new section kind `kind_container = 0x04` to be able to specify zero or more container sections. Each section contains a valid EOF container. ``` container := header, body header := magic, version, kind_types, types_size, kind_code, num_code_sections, code_size+, kind_data, data_size, kind_container, num_container_sections, container_size+, terminator body := types_section, code_section+, data_section, container_section+ ``` > Should data section be the last? [name=alex] > Data is more related to code sections so it does not make sense to separate theses with containers. Containers are used less often than data. [name=pawel] > A thought here should be the current conventions for metadata - currently metadata is at the end of data - if containers are at the end, it's easy to confuse nested container's metadata with the outer container's metadata... On the other hand, we may want to adopt the convention to put metadata at the *beginning* of the data section instead for EOF contracts anyways, which would solve this. But this would mean that e.g. for sourcify EOF wouldn't be transparent anymore. [name=Daniel] > Is `num_container_sections` still 2-bytes for consistency with `num_code_sections`? [name=andrei] > If there are no embedded containers, does the header still include `(kind_container, 0)` (similar to how empty data section is still in the header)? I think it does not to make CREATE3-rollout backwards compatible. [name=andrei] ### Validation Container validation is extended: 1. Each included container section must be a full and valid EOF container. 2. The number of container sections must not exceed 256. > Introduce a "can create" flag in `type[i].outputs`, which marks a code which runs in "initcode" context. Only `code[0]` can have this flag. Then at validation time `RETURN` instruction and other cases can be checked. ~~Conversely `RETURNCONTAINER` should not be allowed in a non-initcode context.~~ [name=alex] ## Execution Semantics Note: in the notation below `{x}` signals an immediate argument and `(y)` signals a stack argument. Note that one aim for redesigning creation is to eventually remove code observability entirely, for this reason consider that `(EXT)CODECOPY` is not available. 1. Data section access instructions 1. `DATACOPY(dst_offset, src_offset, size)` - Copy from data section to memory 2. `DATASIZE` - Returns data section size 3. `DATALOAD(offset)` - Pushes on stack 32-byte value read from data section 4. `DATALOADI{offset}` instruction - Has 16-bit unsigned immediate `offset` - Pushes on stack 32-byte value from data section starting from `offset` (relative to data section start) - Used to efficiently access "immutable storage" constants stored in data section 2. `CREATE3` instruction - A new instruction is introduced: `CREATE3{initcontainer_index}(value, input_offset, input_size, salt)` - Has 8-bit unsigned immediate `initcontainer_index` - Existence of `container_sections[initcontainer_index]` is checked at validation time - Returns 0 on failure - Returns the address on success > Is new account created with nonce == 1? [name=andrei] 3. Initcode execution context (with `RETURNCONTAINER` instruction) - The initcode execution context is reached either via `CREATE3` or the `CreateTransaction`. In this context we already know the address of the newly created account. - Address calculation is performed as: `keccak256(0xff || address || salt || keccak256(initcontainer) || calldata)[12:]` - Difference to [EIP-1014](https://eips.ethereum.org/EIPS/eip-1014) is that `initcontainer` and `calldata` is hashed separately. > Suggestion by lightclient: drop the `keccak256(initcontainer)`. - A new instruction is introduced: `RETURNCONTRACT{embedded_container_index}(aux_data_offset, aux_data_length)` - Is a terminating instruction - New contract's container is constructed as: 1. Take container from the container section `embedded_container_index` - Note that this is container section inside initcontainer that's being executed. 3. Append the memory chunk `(aux_data_offset, aux_data_offset + aux_data_size)` to the container data section 4. Update data section size in EOF header - The instruction can only be executed in initcode context. - Initcode is allowed terminate execution with `STOP`. It keeps the changes done to the state but the new contract is not created. This allows using initcode as ephemeral code. - Initcode is allowed to use `REVERT`, which only populate the returndata buffer. - Initcode is not allowed to use `RETURN`, i.e. the execution results in exceptional abort. - Note: encoding dynamic immediates likely will use "ABI encoding" as a convention > 5. `CREATE`/`CREATE2` are banned in EIP-3670 validation ## Transactions ### Existing transaction types (recap) 1. Legacy transaction - As mentioned in EIP-2718: `rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s])` 2. Legacy transaction with chainid - This is actually the same structure as legacy, only semantics of fields changed. 3. Access lists - As defined in [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930): `0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])` 4. EIP-1559: - As defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559): `0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s])` Remember: Contract creation is signaled with an empty `to`/`destination` field. Creating EOF contracts are not allowed in these transaction types. Transactions with `data` starting with the `EF` byte are invalid and not includable. (This is similar to [EIP-3541](https://eips.ethereum.org/EIPS/eip-3541).) ### New transaction type: `BlobTransaction` (Option 1 -- OBSOLETE) We introduce a new [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) transaction type based on the `BlobTransaction` proposed by [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844). For further clarification on the fields refer to EIP-4844: ```python class BlobTransaction(Container): chain_id: uint256 nonce: uint64 max_priority_fee_per_gas: uint256 max_fee_per_gas: uint256 gas: uint64 to: Union[None, Address] # Address = Bytes20 value: uint256 code: ByteList[MAX_INITCODE_SIZE] # This is the difference from EIP-4844 data: ByteList[MAX_CALLDATA_SIZE] access_list: List[AccessTuple, MAX_ACCESS_LIST_SIZE] max_fee_per_data_gas: uint256 blob_versioned_hashes: List[VersionedHash, MAX_VERSIONED_HASHES_LIST_SIZE] ``` The `MAX_INITCODE_SIZE` is defined in [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) as `49152`. We define create transactions where `to` equals `None`. Options (TODO decide): (`Initcode = ByteList[MAX_INITCODE_SIZE]`) 1. `to` is `Union[Initcode, Address]` 3. `code` is an `Union[None, Initcode]` 4. `code` is simply `Initcode`, but enforce `size=0` for non-create transaction #### Transaction validation 1. Regular (non-Create) transactions MUST have a zero-length `code` field. 2. Create transactions MUST have a non-zero length `code`. 2a. `code` starting with `EF00` must pass EOF validation, otherwise the transaction cannot be included 2b. `code` starting with other than `EF00` is invalid, and the transaction cannot be included 3. The cost of `code` is charged the same as `data`, i.e. 16 for non-zero and 0 for zero bytes (EIP-2028) - (Could consider 3 gas per byte (as per [EIP-4488](https://eips.ethereum.org/EIPS/eip-4488)) given this is bound at `MAX_INITCODE_SIZE`.) #### Transaction execution See below. ### New transaction type: `CreateTransaction` (Option 2) Instead of extending the [`BlobTransaction`](https://eips.ethereum.org/EIPS/eip-4844), we introduce a new transaction type for contract creation, and at the same time ban contract creation in `BlobTransaction` (accomplished with changing `to` from `Union[None, Address]` to `Address`). ```python TransactionType = 0x06 class CreateTransaction(Container): chain_id: uint256 nonce: uint64 max_priority_fee_per_gas: uint256 max_fee_per_gas: uint256 gas: uint64 value: uint256 salt: Byte32 code_container: ByteList[MAX_INITCODE_SIZE] data: ByteList[MAX_CALLDATA_SIZE] access_list: List[AccessTuple, MAX_ACCESS_LIST_SIZE] ``` The `MAX_INITCODE_SIZE` is defined in [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) as `49152`. As it can be noted, this transaction does not support carrying blobs. Transaction validation: 1. `code` starting with `EF00` must pass EOF validation, otherwise the transaction cannot be included 2. `code` starting with other than `EF00` is invalid, and the transaction cannot be included 3. The cost of `code` is charged the same as `data`, i.e. 16 for non-zero and 0 for zero bytes (EIP-2028) - (Could consider 3 gas per byte (as per [EIP-4488](https://eips.ethereum.org/EIPS/eip-4488)) given this is bound at `MAX_INITCODE_SIZE`.) The semantics of this transaction equal to the context of a `CREATE3` instruction, where: - the code executing is `code_container` (which must be valid EOF), - the `data` is accessible via `CALLDATA*`, - the `salt` is the salt used for address calculation. ### Crazy transaction version (Option 3) 1. We change `BlobTransaction` so that it has a `initcode_blob: List[Initcode, 16]`. - Each `initcode_blob` fulfill the validation requirements explained in *Option 2*. 3. We introduce `CREATE4{call_initcode_blob_index}(value, salt, aux_data_offset, aux_data_size)`. - The `call_initcode_blob_index` refers to `initcode_blob[index]`, which is used for creation. - Note that the initcode is not part of the hash, only the salt. - Q: Should this instruction only be available in the outermost tx? 4. We insert a "deployer code" at a known address (let's say `0xA`): ```solidity let size = calldatasize() calldatacopy(32, size) create4{0}(callvalue(), calldataload(), 32, size) ``` *Side-effect:* Assuming this deployer is present at the same address on all EOF-enabled chains, then the created addresses are consistent across. This option allows complete compatibility with features like [EIP-4337](https://eips.ethereum.org/EIPS/eip-4337). ## Code observability After having reworked contract creation, it is possible to consider further restricting code observability (expanding on [banning introspection of EOF accounts](https://ethereum-magicians.org/t/eof-proposal-ban-code-introspection-of-eof-accounts/12113)). 1. Disallow `CODESIZE`, `CODECOPY`, `EXTCODESIZE`, `EXTCODEHASH`, `EXTCODECOPY` in EOF contracts. 2. In other contexts, where they are available, `(EXT)CODE{COPY,SIZE,HASH}` to return a specific value on EOF accounts. ### Option 1 We treat every EOF account as if its code would be `EF00`. This implies: - `EXTCODESIZE` returns 2, - `EXTCODEHASH` returns `keccak256('ef00')`, - `EXTCODCOPY` works as expected. ### Option 2 Mostly we do not change the behaviour: - `EXTCODESIZE` and `EXTCODEHASH` returns the accurate value for both legacy and EOF targets, - `EXTCODECOPY` copies nothing if the target is an EOF account. Additionally we make the commitment that if EOF accounts were to be updated, their resulting size and hash WILL differ. ## Gas observability - Remember that `CALLCODE` and `SELFDESTRUCT` are already disallowed in EOFv1. - Disallow `CALL`, `DELEGATECALL`, `STATICCALL`, `GAS`. - Introduce `EXTCALL`. - This instruction has an 8-bit immediate for `flags`. The flags defined are: - `0x01` - View-context (static call). - `0x02` - Delegate-context. - (This may be a stretch, and perhaps keeping a number of opcodes for these different call types is better. Such as `EXTCALL`, `EXTCALLDELEGATE`, `EXTCALLSTATIC`.) - The stack arguments are: `value`, `destination`, `data_memory_offset`, `data_memory_size`. - The return value is an enum: - 0 - Success - 1 - Failure - 2 - Revert - Note that the gas field and return offsets are removed. - The stipend is removed?

Import from clipboard

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lost their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.


Upgrade

All
  • All
  • Team
No template.

Create a template


Upgrade

Delete template

Do you really want to delete this template?

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Sign in via SAML

or

Sign in via GitHub

Help

  • English
  • 中文
  • 日本語

Documents

Tutorials

Book Mode Tutorial

Slide Example

YAML Metadata

Resources

Releases

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions

Versions and GitHub Sync

Sign in to link this note to GitHub Learn more
This note is not linked with GitHub Learn more
 
Add badge Pull Push GitHub Link Settings
Upgrade now

Version named by    

More Less
  • Edit
  • Delete

Note content is identical to the latest version.
Compare with
    Choose a version
    No search result
    Version not found

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub

      Please sign in to GitHub and install the HackMD app on your GitHub repo. Learn more

       Sign in to GitHub

      HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Available push count

      Upgrade

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Upgrade

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully