EVM Object Format (EOF)

This first step has been accepted for London.

The next step was proposed for Shanghai:

This introduces code - data separation as the main tangible benefit to users.

Watch an overview of EIP-3540 & EIP-3541 by @axic @chfast @gumb0.

There is also a new overview document here:

This gives an explanation of why two hard forks, gives a roadmap of different features we investigate (Shanghai, Cancun, and beyond), and links to all relevant resources.

(We plan to drop the two-hard fork explainer from EIP-3540 to simplify it.)

1 Like

As a further step, we suggest to introduce code validation with EOF: EIP-3670: EOF - Code Validation

It is proposed as a separate EIP to keep concerns separated and the EIPs shorter.

A potential way to remove the need for jumpdest analysis at execution time was published here: EIP-3690: EOF - JUMPDEST Table

1 Like

A proposal made possible by EOF is to have static jumps:

1 Like

After the London upgrade which included EIP-3541 we were able to collect all previously deployed bytecodes starting with the 0xEF byte. The following document has information about collected data and 2 possible EOF prefix values. We recommend the use 0xEF00 2-byte prefix.

EOF Prefix Selection

Has anyone looked into figuring out what https://etherscan.io/address/0xca7bf67ab492b49806e24b6e2e4ec105183caa01 does?

Given that there are only 3 contracts that start with 0xEF and two of them have (in theory) reachable owners/authors and the third doesn’t actually do anything, I think we should explore the option of an irregular state change to get rid of them so we have a completely clear 0xEF space.

This is especially true since all 3 of them were created after EIP-3541 was proposed, and I suspect at least two of them (the contracts that merely deployed 0xEF) were created explicitly to cause problems for us (the third possibly as well, but that one is slightly less clear).

I asked about the long contract here: https://twitter.com/alexberegszaszi/status/1452210984987369474

Writing an EIP for the irregular state change is easy enough, ACD may or may accept it, but it definitely is yet another hurdle to overcome.

I’d be happy if we could get rid of those three contracts, if someone champions that change.

1 Like

Hey there — so that third contract was deployed by me, and it’s just a “farewell” message to 0xef before EIP-3541 took effect. Definitely did not intend to cause any problems with it and would have no qualms whatsoever with the contract being removed if it makes things easier / cleaner.

f09f918b => :wave:
f09f9fa9 => :green_square:

3 Likes

Thanks for the response!

It actually complicates matters, so removing it would be helpful. The other two contracts are annoying too, but cause less issue.

Reviving this now, after having reviewed the EIP a bit. My notes:

The terminator is not particularly well specificed. The only thing it says, is that “If the terminator is encountered, section size MUST NOT follow.”. The>

I suggest that the “Validation rules” are clarified further re terminator.

Example cases. Which of these are ‘valid’ and which are not?
In each case, where it’s not valid, there should be a corresponding rule in the ‘Validation rules’.

// 1.
// 0-size code section, with terminator, no code)

0xEF0001 0x01 0x0000 0x00

// 2.
// 0-size code section, no terminator, no code)

0xEF0001 0x01 0x0000

// 3.
// 0-size code,0-size data, with terminator

0xEF0001 0x01 0x0000 0x02 0x0000 0x00

// 4.
// 0-size code,0-size data, no terminator

0xEF0001 0x01 0x0000 0x02 0x0000

// 5.
// 1-size code,0-size data
0xEF0001 0x01 0x0001 0x02 0x0000 0x00 0xEF


// 6.
// 1-size code,16-size data, but actual code is smaller than that. Does the 'infinite field of zeroes' apply?
0xEF0001 0x01 0x0000 0x02 0x0010 0x00 0xdada


Thanks for the comment.

The intended meaning is that terminator byte is mandatory. But I can agree the specification is not clear about it nor what terminator is.

By following this reasoning, all examples without terminator are invalid (2,4).

It is also specified that "section_size MUST NOT be 0". We decided to include this rule to eliminate two encodings for the same effect - empty section. If a section is empty this forces omitting its header as well. This makes (1,3,5) invalid.

Finally, we also wanted all bytes of a section to be present (no ‘infinite field of zeroes’) but looks this rule is not articulated. That would make 6 invalid. We also don’t allow any bytes outside of sections specified by headers: “Stray bytes outside of sections MUST NOT be present. This includes trailing bytes after the last section.”

In summary, EOF container requires: no implicit bytes, no additional bytes, shorter encoding if two options are possible. The specification does not express this perfectly yet and we will apply fixes.

Thanks. A follow-up question/observation then.

  • If a code section must be present,
  • And a section must not be empty,

Then it’s not possible to deploy a data-only contract. This is IMO a side-effect which deserves mention in the EIP.

1 Like

This was actually desired, though it is still possible to have a contract with a single instruction in the code section (such as INVALID) to have a determined execution path. Agree we should document it.

As a further step to replace dynamic jumps, we propose EIP-4750 (EIP-4750: EOF Functions). This could be adopted together with EIP-4200 (EIP-4200: Static relative jumps) to remove the need for dynamic jumps.

I cannot deploy an EOF where codesize is zero. What if I want to deploy an EOF where I only want the data section and no code?

  1. If PC goes outside of the code section bounds, execution aborts with failure.

This is not entirely in-line with current semantics when PC runs out of code. On a contract where PC goes out-of-bounds the STOP instruction is executed. I am also fairly sure that with PUSH if not all data can be read (e.g. the contract 60, PUSH1 where it is not clear what data should be pushed) then also STOP is executed.

Current EIP changes this behavior; if you run out-of-bounds or PUSH when it is not clear what bytes you should push now goes OOG. Is this intended?

EIP-3670 requires that the code section ends with a terminating instruction, this makes running out-of-bounds impossible and code ending with truncated PUSH data invalid code.

1 Like

Data contracts should have INVALID as the only instruction in the code section to signal they are not executable.