huff-rs icon indicating copy to clipboard operation
huff-rs copied to clipboard

Support 1-byte jump label value

Open minaminao opened this issue 3 years ago • 7 comments

A jump label value is calculated using 2 bytes and the PUSH2 opcode is used, but when the value can be reduced to 1 byte, it is more gas efficient to use the PUSH1 opcode. (200 gas per byte)

https://github.com/huff-language/huff-rs/blob/a4f820a7154c44d1f982e5921d8c24afa4fb0a7c/huff_codegen/src/lib.rs#L374

~An alternative is to support the jumpdst opcode.~

  • EDIT: I found that this alternative is not necessary because even if labels were not used, a jumpdst could still be obtained by labeling it.

(When I was implementing https://github.com/minaminao/huff-eip1167, I wanted the jump using PUSH1)

minaminao avatar Aug 07 '22 08:08 minaminao

I don't think it's that trivial unfortunately, changing a PUSH2 to a PUSH1 makes the code shorter, changing the location of all the following JUMPDEST ops, which could have a recursive ripple effect to previous jumps.

Philogy avatar Oct 24 '22 00:10 Philogy

What if we delegate it to the user? Like annotate if the label is 1 byte, something like my_label:1. The codegen would then output a PUSH1 and err if dest is >255

romeroadrian avatar Feb 08 '23 17:02 romeroadrian

it is more gas efficient to use the PUSH1 opcode. (200 gas per byte)

@minaminao where did you read that? All PUSH operations cost 3 gas except for PUSH0 which costs 2.

PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

costs the same at runtime as

PUSH1 0x00

The only thing that changes is the deployment cost because each non-zero byte in the calldata costs 16 gas and each zero-byte costs 3. So actually by converting

PUSH2 0x0055

into

PUSH1 0x55

you are saving 3 gas for the deployment and zero gas from the runtime.

Mouradif avatar Apr 18 '24 15:04 Mouradif

@Mouradif it means 200 gas per byte of deployed bytecode reference: https://github.com/ethereum/execution-specs/blob/744904ebd0ba8c9ce5ae7c5ee9bef3c5d21a38f9/src/ethereum/cancun/vm/gas.py#L46

minaminao avatar Apr 18 '24 17:04 minaminao

Right now huffc not only supports 2-byte jump labels it'll also break if your contract has more 65kB because it just assumes the labels are always 2-bytes (although that specific bug might've been fixed).

My assembly library evm-glue supports arbitrary jump dest sizes, being able to minimize the destination sizes of all pushes and generally provides a very flexible framework for dealing with and compiling assembly. While it would be a larger refactor swapping it in would fix this issue along with others and make the compiler much more maintainable.

Philogy avatar Apr 19 '24 16:04 Philogy

@minaminao Got it thanks! I wasn't aware of that

Mouradif avatar Apr 19 '24 18:04 Mouradif

I am not familiar enough with the codebase of huff-rs but I made a project that achieves that on bytecode:

https://github.com/Mouradif/evm-bunnyhop-rs

It's not very well tested but it seemed to work on the one contract I'm working on

Mouradif avatar Apr 19 '24 22:04 Mouradif