Only EXTDELEGATECALL
from EOF1 to legacy contract is prohibited, per today’s spec. EXTCALL
and EXTSTATICCALL
are unrestricted. Also legacy can *CALL
EOF1 contracts without restrictions.
Thank you for the clarification. It would be better if such statement was made in full in the EIP.
I.e. we will be able to upgrade the implementation contracts behind UUPS and other proxies (and Diamond libraries), is that correct?
To understand - such stablecoins need to keep the same entrypoint address (mostly proxy now) and basically the storage layout. Implementation contracts can be replaced.
If stablecoins depend on delegatecalling arbitrary adresses not under control of the stablecoin contract then they will not be able to upgrade. Note that this is widely considered to be a security risk.
If however it is delegate calling to contracts controlled by the stablecoin, those addresses need to be EOF contracts. I expect that any such upgrade would deploy the new delegate contracts and then upgrade the core contract, where the core contract is the single switching point for new logic.
Solidity is running a service for source code verification and matadata: https://sourcify.dev
It publishes the ABI/metadata of a contract e.g. on IPFS.
In EOF an anchor to such data may be potentially stored in the metadata section: EIP-7834: Separate Metadata Section for EOF.
A blog post on why we should reconsider EOF: Ethereum is turning into a labyrinth of unnecessary complexity with EOF - Let’s reconsider EOF.
I have co-authored a new and longer EOF deep-dive: EOF: When Complexity Outweighs Necessity. We break down its supposed benefits and argue they’re more “nice-to-haves” than essential upgrades. Instead of adding complexity, we highlight cleaner, less disruptive solutions that achieve the same goals. EOF’s objectives are solid—but there’s a smarter way to get there.
Please give it a read and let us know your thoughts in this thread.
Here’s Solidity’s perspective: The Case for EOF | Solidity Programming Language
In short, we believe the current level of complexity to be justified and mostly overstated. EOF tackles the underlying problems instead of sweeping them under the rug. Some of the proposed alternatives would address some individual pain points for us, but that’s missing the bigger point and only making things worse long-term. We see it not just as a funky prerequisite that’s blocking EIP-663, but as a bundle of tightly related and long overdue fundamental fixes.
Yeah, it won’t make legacy EVM go away, but for most of the stack EOF will quickly become the only part that really matters.
Note: The spec of EIP-3540 is getting a minor update, planned for the eof-devnet-1: Update EIP-3540: Change to max_stack_increase by chfast · Pull Request #9600 · ethereum/EIPs · GitHub
Another minor update, planned for eof-devnet-1 (section kind for data section 0x04
→ 0xff
) Update EIP-3540: Change kind_data from 0x04 to 0xff by pdobacz · Pull Request #9502 · ethereum/EIPs · GitHub
Final eof-devnet-1 update - 4-byte container size to accommodate increasing codesize limits Update EIP-3540: Make container section size 4 bytes wide by gumb0 · Pull Request #9581 · ethereum/EIPs · GitHub
I posted this in the agenda for today’s ACDE meeting, and it seems that ACD has already decided on moving forward with EOF for Fusaka. However, I wanted to post this here to record Vyper’s position on this future reference so that it doesn’t get lost in Github issues.
The TL;DR is:
- Vyper doesn’t see substantial benefits from EOF
- EOF creates a large amount of work for us, with practically no benefit
- It breaks developer assumptions, and requires them to hold two mental models when developing for EOF vs non-EOF
- It takes attention and energy away from other improvements which the EVM badly needs, such as fixing memory and transient storage pricing (and with it, lowering the barrier to protecting against reentrancy), fixing the 63/64ths rule, code size limit improvements and
PAY
opcode - All the benefits around static jumps can be shipped in a much less invasive way, which is a lot less burden for us to implement and maintain (and probably allow us to generate better code!), and without breaking developer assumptions
In summary, I believe that moving forward with EOF would be a serious mistake for Ethereum and hurt its competitiveness. It demonstrates to app and tooling/compiler developers that we do not care about the stability of the VM, and permanently (or at least for multiple years) increases the maintenance burden of apps and compilers across EOF and non-EOF ecosystems.
For the record, I also will post some of my responses from that github thread.
- The EVM Resource Pricing Working group operates independently of the EOF efforts. I assert we are not holding them back. See their last meeting notes here. I look forward to the proposals from this working group and the changes the “Gaspocalypse” will bring.
- The EIPs listed for a less invasive way were all separately propsoed and rejected by the ACD process. This includes EIP-615, EIP-1702, and EIP-2315. EOF was crafted with the reasons for rejection in mind. Note that EIP-4200 was always presented as a part of EOF.
I am personally of the opinion that a strong container format is essential for the continued competitiveness of the EVM, as other smart contract VMs have brought up the lack features EOF provides in a number of contexts as to why their solution is better.
That’s simply not true. A litany of EIPs were rejected for Fusaka the other day just on the basis that EOF is already enough to implement for a single hard fork, including a memory repricing EIP.
I don’t think this is a strong argument against those EIPs. There is a lot of precedent where EIPs were rejected for one hard fork but included at a later date.
I’ll take your word for it, but developers are still preferring to use the EVM. I’d hazard to say that developers prefer to use the EVM due to its stability and network effects. EOF runs counter to that stability. This is not about ossification or not ossification, but if upgrades are truly needed, can we upgrade in a smart way?
Some more responses that I had drafted for that github thread (but wanted to avoid spamming after timbeiko stated it would not be on the call agenda):
The attitude I have heard expressed on ACDE and EOF calls is very much that, going forward, ACD will not ship any more improvements to non-EOF EVM. So in practice, non-EOF EVM will be a no-go as a compilation target for mainnet.
There hasn’t been a formal policy for that yet. The best argument for only adding new opcodes inside the EOF container is the claim that nobody will use them outside an EOF container.
Yes, people will absolutely want to use PAY
outside of EOF. The case for this is pretty clear if you think about it from the perspective of the user. If they write code for EOF and then need to deploy it on a non-EOF-supporting chain, then the code will either not deploy or worse, behave differently than it was intended to (depending on how PAY
is exposed in the high-level language). This is one of my chief arguments against the current EOF package, which is that it breaks developer assumptions, sometimes in subtle ways, and often without even meaning to.
I already have people coming to me complaining that they have to recompile code for L2s that don’t support PUSH0
– and that one is just an opcode which has the same semantics as PUSH1 0
, but just doesn’t deploy pre-Shanghai. What is going to happen when their code deploys, but actually has completely different semantics(!)?
EIP-2315 does not prevent the natural flow of code from entering or exiting a subroutine context. While there is disagreement as to wether or not it is a good thing or a bad thing it was one of the technical arguments that people opposing it (including @lightclient) found persuasive.
Given that @matt also opposes EOF, I’m not sure that this really moves the needle on the argumentation for it or against it.
EIP-4200 requires immediate data, which breaks the current jumpdest model, and would require a separae validation regime.
These three EIPs give you full freedom from JUMPDEST
analysis.
I agree it is a simpler design, but for the problems they solve they are too simple and will inhibit good solutions to other issues the EVM faces.
Simple solutions are good! Also, I’m not sure which issues are inhibited. For every single issue I’ve seen that EOF is supposed to solve, my take is that it’s either solvable without the full EOF package, or the fact that EOF has to coexist alongside non-EOF, forever, means that the problem is presumptively solved, but in practice, only halfway (e.g. gas introspection).
The yellow paper specifies that the PUSHX instruction is carried out using the available bytes and right padding with zeros if the bytecode runs out. This is consistent with how (EXT)CODECOPY append 0’s to the right of byte code when the actual byte code runs out.
@charles-cooper EOF provides the one benefit I most care about: It becomes possible to traverse the flow of control of an EVM program in linear time. In the current EVM that is impossible. Which means that linear-time validation, symbolic execution, and compilation of EVM code is impossible. My own work has been stymied for ten years now for that reason, and lots of other people’s work has been made difficult to impossible as well. So I’ll put up with a lot to get that benefit.
The current version of EIP-2315 depends on the earliest parts of EOF to separate code from data and provide for immediate arguments and relative jumps anyway. Do you find those parts of EOF be a problem?
The remainder of 2315 amounts to an alternative to EOF Functions and Stack Validation. Subroutines in 2315 take up less space and can be better optimized, but provide fewer safety benefits. Do you find EOF Functions to be a problem?
The rest of EOF I’d be fine with postponing, but if EOF Functions don’t get in I fear that nothing will get in before I die.
Preventing global jumps is obviously an impediment to optimization. And given a stack validation function it provides little by way safety – validation of EVM code provides discipline at the semantic level that high-level languages provide by syntactic restrictions. High-level languages disallow global jumps and lots of other constructs on the theory that it’s better to protect the programmer and let the optimizer do the dirty work. But EVM code is the output of an optimizer, and EOF needs special opcodes to provide just some of the optimizations that global jumps can provide.