Meta: Stop extending the EVM with Precompiles, Use Opcodes

As someone who developers compilers for the EVM (Huff and now new language “Plank”) and occasionally handwrites EVM bytecode I wanted to make a plea that future extensions of the EVM be made using Opcodes instead of Precompiles.

My reasons are the following:

  • Precompiles as an interface are much more expensive and cause larger bytecode than simply having opcodes
    • Precompiles behaving as “contracts” require all their inputs to first be placed into memory requiring several MSTOREs even when inputs are constant in size/number
    • Calling pre-compiles requires a (STATIC)CALL instruction which the EVM charges 100 gas for
    • Outputs requires reading them out from memory with MLOAD instructions even when outputs are constant in size/number
  • There’s a lot of unused space in the EVM instruction table to define new opcodes
  • Extending the EVM via opcodes is arguably less breaking than pre-compiles:
    • in order for a new opcode to be breaking for a contract it requires contracts to have a reachable undefined instruction instead of the explicit INVALID opcode
    • precompiles in contrast make a new address a valid call target and potentially arbitrary behavior/return characteristics
2 Likes

I get why precompiles are ugly and slow at the opcode level.

The biggest problem everyone is trying to solve is typically that they can be added to a chain without requiring compiler changes in order to be able to use them. For most projects, that’s an insurmountable barrier. Instead a precompile lets someone just distribute an ABI or interface file and anyone can use it in existing tooling.

One way forward here is make it so that languages/compilers can call opcodes that aren’t built in.

(This is at least from the perspective of still EVM, but non-Ethereum chains looking to add features)

(Even though that’s a secondary consideration, EIP-8163 is a minimal step towards solving the limited number of opcode concerns)

4 Likes

I think there’s a chicken and egg situation going on here:

  • Compiler teams have limited resources so they only invest in things that are immediately useful
  • New opcodes are rarely added so they don’t have ways to use custom/new opcodes
  • There’s no way to easily use custom/new opcodes so client teams extend the EVM as precompiles

I think the recent historical example of TSTORE/TLOAD also showcases the teams’ willingness and ability to quickly adopt and implement new opcodes.

If we can come to consensus that on a purely technical level opcodes are superior then I think moving to do that going forward sends the necessary signal needed for compiler teams to continuously integrate new opcodes as they arrive and/or make it possible to define & use custom opcodes.

2 Likes

Agree adding extensions via opcodes could make a lot more sense for the reasons you outlined.

Extending the EVM via opcodes is arguably less breaking than pre-compiles

While not breaking contracts themselves, one consideration is the impact on downstream tooling. Both precompiles and opcodes require changes to client implementations. Opcode changes also require support across the broader tooling stack. For example, while the compiler is already mentioned, opcode support also needs to be added to the EVM implementations used by development tools (forge/hardhat).

I agree the implementation overhead could be worth it (especially in an AI-accelerated development paradigm), although it does introduce additional coordination overhead.

2 Likes