Inspiration

The eth_sendTransaction RPC call, when you omit the to field, is designed to run calldata as opcodes for arbitrary execution associated with the address of the future contract address to be created, to allow for the behavior of a constructor. Technically, it does not even have to result in a contract creation.

A couple weeks ago I had a dream that I attempted the eth_sendTransaction trick with eth_call, by omitting the to field in the payload, and it behaved similarly. I tested it out at some point, and it turns out it actually worked. So this would theoretically allow you to write compact evm snippets that performed complex data aggregation tasks across the network and format a massive return buffer and offload as much client side processing to an RPC cluster as you wanted, especially when existing view layers were non existent, inefficient, or otherwise not worth the gas money of deploying your own, especially when the nature of the queries on your dapp are updating in complex ways.

What it does

The emasm project (ethereum macro assembler) expresses an AST for evm assembly modeled like Huff, the assembler used by the AZTEC team. The AST is quite literally a JavaScript nested list structure. Nested lists that begin with a jump label whose next element is a list of opcodes define a jumpdest location you can reference with the jump label, similar syntax exists for raw bytes in the binary for use with codecopy, all other lists, no matter how deeply nested, are assembled as opcodes, and everything, including segments, is assembled in the order it appears.

A JavaScript IR written efficiently gives you a rapid way to assemble eth_call payloads and encode all the inputs to your query as PUSH instructions, since writing a "macro" in emasm is just writing a JavaScript function that creates or operates on a list.

How I built it

I created a table of opcodes, and designed logic for passing over nested lists in as few passes as possible to encode static pointers accurately in the final pass.

Challenges I ran into

Silly things involving off by one errors when calculating the size of final segments and the minimal jumpdest push width, etc

Accomplishments that I'm proud of

I have never heard of this eth_call trick, and I'm not sure if it exists as an unintended consequence of RPC call objects. I'm not sure if I am the first to discover it has a use case.

What I learned

A lot! As discussed.

What's next for emasm

Extra function to validate an AST for errors, and generic ABI encode/decode macros

Built With

Share this project:
×

Updates