Skip to content
This repository has been archived by the owner on Sep 9, 2024. It is now read-only.

Support 1-byte jump label value #200

Open
minaminao opened this issue Aug 7, 2022 · 7 comments
Open

Support 1-byte jump label value #200

minaminao opened this issue Aug 7, 2022 · 7 comments

Comments

@minaminao
Copy link

minaminao commented Aug 7, 2022

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)

let jump_value = format!("{:04x}", jump_index);

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)

@Philogy
Copy link
Contributor

Philogy commented Oct 24, 2022

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.

@romeroadrian
Copy link

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

@Mouradif
Copy link
Contributor

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.

@minaminao
Copy link
Author

minaminao commented Apr 18, 2024

@Philogy
Copy link
Contributor

Philogy commented Apr 19, 2024

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.

@Mouradif
Copy link
Contributor

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

@Mouradif
Copy link
Contributor

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants