EVM Object Format (EOF)

But in the case of an EOA recipient it should not!

The extcodesize check is not redundant, it’s necessary to implement the semantics.

2 Likes

Ah, you’re totally right. I misread the purpose of the check in these EIPs. It’s there to skip the onReceived() calls without reverting. Without it the EIPs will still work for contracts but not for EOAs.

So yeah, this does seem like a new use case for the check. I still think it does not make the EIPs unimplementable though, it just neuters some of their safeguards, which previously wasn’t considered a strong enough reason for an additional call return code.

The way you’d implement it without the check would be for ‘safe transfer’ to always issue a call and check whether it’s an EOA based on the status and return data. If the call is successful and the return data is empty, it’s probably an EOA. Of course this will have some false positives, e.g. if it just happens to be a contract has an onERC1155Received() function that returns nothing. Or if the contract intercepts the call in its fallback function.

I don’t think this is qualitatively different from the case of the extcodesize check on high-level calls in Solidity that we brought up earlier. Still, if this additional case is enough to sway the decision towards making this case properly distinguishable, I’m all for it.

EOF Call 52 notes

  • Clients
    • Besu and EVMONE are adapting to recent spec changes
    • Nethermind and Geth are progressing with their implementations, currently working on state test issues
    • EELS has started an implementation
    • No updates from Reth or EthJS
  • Compilers
    • No updates from Solidity or Vyper
  • Spec Updates
    • Discussed the need to differentiate EOAs from contract accounts, for ERC-721’s safe transafer from method
      • Two major options: return codes (as outlined above) and reworking EXTCODESIZE
        • Return codes could be tweaked to set high bits for flags. bit 7 - failure, bit 6 - was an EOA bits 0-3 status.
          However, this could impose overhead for contracts that don’t care about EOA status
          Ipsilon will ping @rodiazet to see if we can quantify the overhead we would see out of solidity
        • EXTCODESIZE could be recast like DIFFICULTY/RANDOAO was recast.
          A new IS_CONTRACT opcode would overlay it, returns 0 if it has no code and 1 if it does, regardless of size. Compiler logic that only tests codesize > 0 would still work.
          The downside is this is an infringement of banning code introspection. While not a bad one as it is a simple question of “do you execute code”
    • Discussed changing max_stack_height in the types section in light of the requirements for input_size already existing, so that a double counting can be removed from CALLF checks.
      There were concerns about a non-essential change going in this late, however @chfast was not on the call it was decided to push it out two weeks when he can be present to advocate for his change
    • Banning EOFCREATE and RETURNCONTRACT referencing the same container was finalized
  • Testing updates
    • We discussed the issues around system contract actions such as beacon block, block hash, and withdrawals/deposits/consolidations.
      A new field will be added to the “env” section of t8n requests indicating if those block level action should or should not be performed. This will allow state tests to evaluate just the TX and not the whole block.
    • We also discussed differentiating initcode and runtime code in EOF container validation tests. a new field will be added allowing test consumers to differentiate. PRs will be forthcoming.
  • Devnet
    • Because we do not have multiple clients ready we will not be launching a devnet in June. Target is now July.
    • Kurtosis is ready to support EOF networks. Assertor tests need to be written to deomnstrate basic readiness for EOF create transactions.

Next call is in 2 weeks, on 10 July. Danno and Piotr will be absent.

2 Likes

The max_stack_height change is rather cleanup but it also leads to bigger change removing the need for runtime access to the type section (please discuss the details there). In my opinion this is worth the effort especially for the code chunking.

This is late, but I’d like to answer the VLQ question in the context of instructions. For EOF header this is probably fine, but I’m not sure how much it matters there.

For instructions VLQ doesn’t look good. EOF makes bytecode translation much easier (JIT/AOT compilers) but also improves situation for interpreters by a lot by removing jumpdest analysis. I.e. interpreters can start executing just after reading the EOF header.

Using VLQ to encode instruction immediates makes the interpretation more complex because for some instruction VLQ decoding is involved and it is rather impractical to cache the results or preprocess the code. For some instructions like RJUMPV VLQ cannot be used normally because random access to the table is needed so we need a workaround in this case.

sorry, missed the last meeting as I was taking a vacation!

I think this is the same as IS_CONTRACT opcode, since you can always (static)call an address and check the status code to deteremine if it is an EOA. But I guess you can always bust out and call a specially designed legacy contract to query the code of a given address right?

I think this should be run by the AA folks tbh and see what they think, as I have seen a lot of calls for “shouldn’t be able to tell difference between EOA and contract”, not sure if the ERC721 safeTransfer case has been considered.

Hmm I think for almost all instructions with immediates there is an improvement, since there is no limit on the addressability size. For example, with VLQ we could add fewer stack instructions; a single opcode with variable length could be used for SWAPN/EXCHANGE. And from a performance point of view VLQ is an improvement since in common code patterns it improves codesize.

RJUMPV is indeed a special case which would need its own encoding to preserve the property of random-access to the table. (But I don’t think it’s a particularly hard problem to solve, it just needs a bit of spec work).

By the way, these are already all discussion points that were addressed in the VLQ proposed addition to EOF update EOF container specs with variable-length encodings by charles-cooper · Pull Request #37 · ipsilon/eof · GitHub.

I’m extremely late to the party, but am I reading EIP-3540 correctly? It seems that both the entire EOF blob and one of the section kinds are called “containers”. That seems like confusing terminology.

hey, so i implemented an onchain interpreter

i wanted to confirm that

https://github.com/rainlanguage/rain.interpreter/blob/main/src/lib/eval/LibEvalNP.sol#L146

would be implementable with RJUMPV and retain constant time function calls here

it looks like RJUMPV might be able to replace my hand rolled assembly, which would be nice, but i also might be missing something here and if i can’t do what i need in EOF that would be a problem for me

You would need to change your function encoding to an int enum from 0 to 255. And you would be limited to 256 functions. Or you would need to stack dispatchers, one for the first byte, jumping to one for the second, etc.

EIP 3540 does not have rationale for removing EXTCODE access. It should be mentioned and alternatives should be discussed.

1 Like

Agreed on the missing rationale, will track this. The currently proposed substitute is EIP-7761 HASCODE instruction, alternatives to it are also discussed there.

How will eth_getCode behave for EOF? Will it return EF00 like EXTCODECOPY, the full object, or the code segment?

By the name you are referring to the JSON-RPC API eth_getCode, correct?

The EIPs only handle in EVM execution, so the JSON-RPC specs are out of scope and no change in the APIs is proposed.

That being said, I expect it should return the entire EOF code object as it exists in the account trie. The concerns about code introspection are only for introspection within the EVM, not from the outside. For cross-layer concerns like the JSON-RPC, I don’t see how we could possibly enforce non-introspection, as you could just re-play all the transactions (which executing contracts don’t have access to).

1 Like