Ethereum is turning into a labyrinth of unnecessary complexity with EOF - Let's reconsider EOF

Underlying point is understood. Still, I find the specific technical details useful to discuss. I am trying to understand and try propose solutions for the problems you are facing (c.f. the TXCREATE case).

So if that’s not a problem, I have only two quick follow-ups for now:

In EIP-7069 EXT*CALL discriminates between revert and oog of the callee (or any other failure consuming all callee gas) via the returned status code - 1 vs 2. Does that help? Would other status codes help?

What if EXT*CALL allowed to customize the gas forwarding rule to a relative amount, i.e. forward “x/64th”? This is an draft idea which floated recently, not fully sure if viable yet.

1 Like

I wrote a lot of Uniswap V3 so let me comment on this. O(10%) is not a good ROI for the amount of mental overhead EOF introduces for me as a dapp developer. Bytecode size is irrelevant as long as it’s under 24kB, especially with newer singleton designs as in in Ekubo Protocol, Balancer V3, Uniswap V4. The singleton design of these contracts saves much more than 9% in contract calls and storage reads/writes. Simply introducing a usable account abstraction removes approval transactions, and that probably scales the blockspace by more than 10%. You could save even more by building swaps into the account to remove approvals. I often find major improvements in gas costs simply by dropping down into assembly, so the solidity optimizer is far from optimal. All that to say, 10% usually comes at a cost of far, far less complexity.

I also don’t see the scaling benefits of EOF as significant. IMO you can do way better than a 15% speedup on execution if you focus on parallelization, e.g. introduce a new TX type that has mandatory access lists + incentivize it with gas refunds for accuracy.

I don’t argue with the benefits of EOF, I take issue with the immeasurable complexity cost of those improvements. If your EIPs need 30k tests to be safely deployed and only save 10% gas on execution, maybe it’s not worth it. For context, Ekubo Protocol has about 350 unit/fuzz tests, Uniswap V3 had about 1k unit tests, and transient storage has what looks like a few dozen.

Edit: can’t find where I saw the 30k tests number, so striking it out

2 Likes

Well, it’s not completely irrelevant, it actually relates directly to gas price, per your example. Gas price may have been 1gwei for all of Feb, but gas prices fluctuate, and that low price is not eternal. People definitely complain about deployment cost when gas was high, especially for more dynamic use cases such as we expect with account abstraction.

1 Like

It’s quite interesting to see a team being criticized for writing too many tests. And your estimate of 30K is off by about an order of magnitude.

Ethereum testing has evolved quite a bit since TSTORE was added. Compared to the old JSON based testing EEST makes writing lots of tests easy because it has a very expressive parameter system based around python. It makes it easier to fire off 90 tests rather than find the 5 most representative failures, so it takes a bit of restraint to not quickly carpet-bomb the testing area because pytest makes it very easy to do so. Judging complexity by test load is not very insightful because it’s actually fun to write EEST tests, as opposed to the monotony of other testing systems.

And the comparison to a narrowly focused DeFi swapper for complexity is not an apt comparison. Ekubo does one thing well, and a VM need to do, well, basically everything.

If we hyper focus on the smallest possible change we will never be able to correct the mistakes that were made in the first draft of the EVM: dynamic jumps, no container system, no subroutines, etc. If there was a serious VM person in the pre-olympic days I bet we would at least have a container, and that alone would solve lots of problems.

For example, if we had a container we would have a place to store metadata about what storage slots are touched based on the input and we could more intelligently decide what transactions need to be examined for conflicts, and parallelize the rest. Instead without it we would have to enumerate those conflicts and incentivize correctness, rather than make it an easily computable part of the program.

The perception of the complexity is we are adjusting some fundamental assumptions that are holding the EVM back, and as devs we understand where all the touch points are.

3 Likes

Sorry, can’t find where I first saw that number, so striking it out.

For reference, I was counting from here: execution-spec-tests/tests/cancun/eip1153_tstore at v3.0.0 · ethereum/execution-spec-tests · GitHub

This point has surely been made a few times by others, but you can’t actually correct the mistakes because the existing contracts will never go away. If you could migrate or otherwise get rid of old contracts, I wouldn’t have any issue and might even be excited about EOF. It might be on your roadmap, but I see no practical way to migrate existing contracts, and at least it’s a huge effort for what amounts to O(10%) cost reduction.

Your reply about it looking the same to EVM developers does not sound right to me. I regularly drop down to assembly blocks and I basically have evm.codes open all day long. It’s critical to understand exactly how the EVM works and what solidity is doing under the hood when gas or safety matters, and I also need to know how EOF contracts interact with non-EOF contracts and vice versa.

I don’t think it’s even desirable to have that metadata on-chain. You can just simulate the transaction off chain, and/or the dapp will contain the logic for determining the slots that are touched. If you priced the theoretical mandatory access lists TX correctly, then the dapps would be incentivized to be as precise/accurate as possible.

4 Likes

Your reply about it looking the same to EVM developers does not sound right to me. I regularly drop down to assembly blocks and I basically have evm.codes open all day long. It’s critical to understand exactly how the EVM works and what solidity is doing under the hood when gas or safety matters, and I also need to know how EOF contracts interact with non-EOF contracts and vice versa.

strong++ to this

1 Like

So adoption of EOF now relies on the words of some random engineer at OP?

This is very very sad.

To be clear, I am not saying that EOF is a bad idea. Bytecode versioning is great. But it is something that EVM should have been initially designed with. Now we would just add a ton of technical debt instead of addressing it.

Once again, EOF would only see light if most of the EVM chains adopt it. Otherwise, EOF would become another weird kido like push0 or transient storage.

Why can’t we see some coordination efforts from EF? Why there is no official L2 rollup stack that would support all the latest Ethereum changes? Why are we focusing on EOF instead of scaling the L1?

1 Like

I know where you’re coming from and I agree of course. But at the moment whether contract deployments are 5% more or less really doesn’t matter. My main concern is wasting time and Ethereum going to shit because it’s core mechanics are unfixed in production for over a year now. I don’t think we can take for granted that gas prices will come back to prior levels with the system so fucked up. I imagine EOF can also be done at a time when things aren’t on the edge collapsing?

As a consumer product builder IMO “people complaining” is usually not a proxy for “I need to optimize something” but it is a proxy for “wow we have created something so valuable that when we bar people from it they start to complain/bargain with us.” Everyone says the iPhone is too expensive…

Anyways, just to be clear about my intent. I complain here bc I don’t see how EOF is addressing the most pressing issues that the Ethereum software currently has and therefore, for now, I’m against doing this effort.

But what do you think are the most pressing issues of Ethereum then? Because making the lifes of SC devs easier is quite high in my priority list. Among other things, EOF should enable better tooling and make developing on Ethereum easier. Doesn’t this address your concerns about SC development being too expensive for example?

1 Like

This is the strongest point yet that something is fundamentally broken with the EVM in general or at least Solidity. We can’t expect all the devs to know how to write assembly in order to be productive.

According to Electric Capital’s 2023 only around 0.085% of all software developers work in web3 full time. Meaning that if blockchains become as important as we all think the vast majority of devs is yet to join and start working on smart contracts. We need to make their entry as easy as possible. Solidity thinks that EOF helps write compilers so that’s a good start for me. I don’t know which other steps are needed, but needing assembly so often seems to be a bug that needs to be addressed.

1 Like

(source: Ethereum financial statement | Token Terminal)

Ethereum has stopped making money for its holders. Check the fee accrual row. Ethereum was mechanically worth a lot of money as a business because if you owned it you’d get access to between 9B to 2B USD in annual fee accrual. Plus you’d also get all the fees from Flashbots. Because of a (frankly) half-assed update fee accrual is now 10x less for 2025 with no direct path to going up again. Why should ETH price not follow this decrease in cashflows and go 10x down?

(btw I’m far from the only person who sees ETH evaluation like this: Ethereum Must Choose: Asset or Platform, Says EY’s Paul Brody - "The Defiant")

“Bitcoin is the asset. Ethereum is a platform,” he said. “Ethereum doesn’t need to be highly valuable, but fundamentally, the valuation of Ethereum is based on a discounted cash flow model. It generates transaction fees. You stake it, you get yield. It’s actually really simple.”

(I disagree with ETH “not needing to be highly valuable” as economic security is important for the chain. Anyways I’m quoting this to confirm that other’s value ETH based on discounted cashflows too).

What? “More users are going to surely come soon?” That feels way too optimistic to me. Just because we’ve built it doesn’t mean they’ll come. Solana has also built it and their fee accrual is more than ours for this year already.

So this is the starting point and every one of us has to do everything we can to fix this in one way or another. Sorry, I’m sure the EOF work was done in good faith ofc, but embarking on a big “refactor” for some minor optimizations seems to me like a very foolish idea considering that it is taking away overall capacity from the core dev team to addressing the core issue. If everyone’s busy with EOF they may not spend time fixing the main issue more directly

Okay, but that is completely off topic, I thought you meant changes to the EVM. I do not think that a post about EOF is the right place to discuss ETH value accrual.

3 Likes

Why would that be off topic? This is literally the single most important thing in all of Ethereum. Neither of our fault that it was broken but it is now an existential issue. But we have to deal with it anyways. If that doesn’t work we also don’t have to discuss a refactor of the code base because the code base won’t matter anymore

Guys, 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.

2 Likes

Actually it is usually entirely solidity’s fault, just take a look at all the simple functions in the solady library that are cheaper by avoiding solidity’s bytecode generation. Hence my suggestion that the energy be shifted towards the language and compiler for a much higher ROI.

Here’s an example: Writing a struct that fits in a single slot incurs additional SLOADs in Solidity 0.8.29. The assembly-only version costs 125 less gas, even though the result is identical.

pragma solidity =0.8.29;

import {Test} from "forge-std/Test.sol";

contract Target {
    struct MyStruct {
        uint64 a;
        uint64 b;
        uint128 c;
    }

    MyStruct public state;

    constructor() {
        state = MyStruct(3, 2, 1);
    }

    function solidityOnly() external {
        state = MyStruct(1, 2, 3);
    }

    function assemblyOnly() external {
        assembly ("memory-safe") {
            sstore(0, or(or(1, shl(64, 2)), shl(128, 3)))
        }
    }
}

contract TestWasteTest is Test {
    Target t;

    function setUp() public {
        t = new Target();
    }

    function test_solidityOnly() public {
        t.solidityOnly();
        vm.snapshotGasLastCall("solidity only");

        (uint64 a, uint64 b, uint128 c) = t.state();
        assertEq(a, 1);
        assertEq(b, 2);
        assertEq(c, 3);
    }

    function test_assemblyOnly() public {
        t.assemblyOnly();
        vm.snapshotGasLastCall("assembly only");

        (uint64 a, uint64 b, uint128 c) = t.state();
        assertEq(a, 1);
        assertEq(b, 2);
        assertEq(c, 3);
    }
}

And I disagree with the premise anyway. If you are writing contracts that will handle billions of dollars, sorry but you’re going to need to have a deep understanding the platform you’re building on. EOF is going to make that a much bigger hurdle.

2 Likes

Stack validation can be done, but in the presence of dynamic jumps it cannot be done in linear time – every possible path out of every jump must be traced, taking quadratic time. The same problem afflicts anything that involves tracing the control flow of a program, including compilers of EVM bytecode to machine code.

The EVM has no subroutine instruction. Instead, they are implemented with dynamic jumps. We have been arguing about whether and how to remove dynamic jumps and add a subroutine instruction to the EVM for ten years now.

3 Likes

This sub-topic appears to be diverging from the main discussion, perhaps we ought to take it to another thread. Regardless, here’s some more discourse around the specific technical points raised before:


Ahh, so THAT’s what that does. That doesn’t all the way solve the problem. As you can see in the first contract that I linked and in this conceptually-similar block in another contract for the same protocol https://etherscan.io/address/0x00000000000000cf9e3c5a26621af382fa17f24f#code#F1#L103 , finding out whether the next-childward context reverted exceptionally isn’t sufficient because we may need to find out whether a contract some number of contexts away from us reverted exceptionally. An example of this would be protocols with nested proxies, but the specific use case that this contract is designed for is DEX routing wherein a DEX may be a proxy (i.e. the context stack may be MultiCall → router (generic) → router (specialized) → DEX (upgradeable proxy) → DEX (minimal proxy) → DEX (implementation) → oracle (proxy) → oracle (implementation) [yes, this is a real context stack that I’ve encountered in production] and we want to make sure that the oracle got enough gas). In the example, we’d just set contextdepth = 7.

I’m not sure if there’s a good way of retrofitting this into the existing EIP in a way that isn’t intrusive, but I would appreciate a suggestion for how to support this use case. I think that @pcaversaccio hit the nail on the head on HackMD:


I think that solves the problem in the case that you know the relative gas consumption of the pre- context in terms of the post- context, but that may not be sufficient in general. Perhaps a more elegant solution would be to forward gas (up to) some proportion of the block gas limit?

1 Like

This is resolved by the PAY opcode slated for EOF devnet-2

Hi,

I work on hevm, a symbolic execution framework for EVM with over 5k commits. What I can say is that EOF will significantly lower the burden of doing formal verification of contracts. And there’s some really good reasons why that’s important. Hacks are an issue. But so are bugs (e.g. funds accidentally locked in). All serious crypto systems do formal verification of their code, be that AAVE, Uniswap, etc. These are not small players, and I’m pretty sure some people on this very thread trust these systems with some serious money. If you want these, and similar systems to thrive, you need to make sure they can be formally verified. EOF helps with that in a big way. I don’t think I need to go into details of what’s wrong with no separation of code and data, and basically impossible-to-disentangle control flow graphs. But I will anyway. It’s hard. Sometimes very hard, and sometimes impossible without human help (which can not only be costly, and delay verification work, but can introduce errors). Now, of course, if you are willing to spend a few million USD, Certora will disentangle that for you, no worries. But… innovation in the application space will suffer for it due to the delay, uncertainty, and monetary barrier it introduces. Furthermore, it unnecessarily raises the barrier of entry for tools that perform formal verification of contracts – and it’s already a pretty high bar.

I can’t comment on many of the things that are said here, and I don’t want to – they are outside the scope of my expertise. What I am an expert in is formal verification (wrote a SAT solver, and a model counter that are quite widely used), and I worked a lot in the IT security space (at one point having written code that broke >60% of all car anti-theft systems on the road). Based on these experiences, my opinion is that (1) we need formal verification or bugs will slip through and (2) without EOF, formal verification of contracts is gonna keep on being harder than it needs to be.

Just my 2 cents,

Mate

PS: I am also in favour of (1) mature and (2) well-thought-through proposals that (3) solve the CFG & data/code separation issues that (4) have a serious chance of being accepted and implemented. As they say: “Scientists are treacherous allies on committees, for they are apt to change their minds in response to arguments”.

11 Likes

Here’s Solidity’s perspective: The Case for EOF | Solidity Programming Language

6 Likes