Skip to content

Commit b2a1d9d

Browse files
authored
Allow to use built-in functions in constant assignment (#33)
1 parent 0fe9d8d commit b2a1d9d

File tree

18 files changed

+252
-49
lines changed

18 files changed

+252
-49
lines changed

CHANGELOG.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,25 @@
33
# Huff Neo Compiler changelog
44

55
## [Unreleased]
6+
7+
## [1.1.0] - 2025-02-02
68
- Support for constants in code tables.
7-
- Use correct code line for error messages in code tables for builtins.
9+
- Use correct code line for error messages in code tables for built-ins.
810
- Switch to Foundry's print function for trace logs.
9-
- Allow to use `--target-address` to specify the contract address during a test.
11+
- Allow using `--target-address` to specify the contract address during a test.
1012
- Disable base fee check for tests.
1113
- Allow uneven bytes for code tables e.g. `0x1` is valid and results in `0x01` bytecode.
1214
- Introduce new lexer token type `Bytes`, as not all hex should be parsed to bytes32.
13-
- For constants in code tables the bytes are copied as defined with e.g. leading zeros.
14-
- For all other cases leading zeros are removed and the smallest push operation is used.
15-
- New built-in function `__LEFTPAD` to a hex input or a function result in a code table.
15+
- For constants in code tables, the bytes are copied as defined with e.g. leading zeros.
16+
- For all other cases, leading zeros are removed and the smallest push operation is used.
17+
- New built-in function `__LEFTPAD` to a pad a hex input or a function result in a code table to the left in 32 bytes.
1618
- The function can only be used in a code table.
1719
- Example: `__LEFTPAD(0x123)` -> `0000000000000000000000000000000000000000000000000000000000000123`
1820
- Allow to pass a constant as a parameter to `__RIGHTPAD` or `__LEFTPAD`.
1921
- Example: `__RIGHTPAD([CONST])`
22+
- Allow to use built-in functions in constant assignment.
23+
- Example: `#define constant FUNC_TEST = __FUNC_SIG("test(uint256)")`
24+
- This solves the issue to define functions with the same name but different arguments.
2025

2126
## [1.0.10] - 2025-01-31
2227
- Add windows binary to the release.

book/SUMMARY.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Summary
2-
- [Getting Started](get-started/overview.md)
3-
- [Installation](get-started/installation.md)
2+
- [Getting Started](get-started/getting-started.md)
3+
- [About Huff](get-started/about-huff.md)
4+
- [Comparison to huffc](get-started/comparison-to-huffc.md)
45
- [Compile a contract](get-started/compiling.md)
56
- [Project Quickstart](get-started/project-quickstart.md)
67
- [Huff Language](huff-language/overview.md)
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
# Getting started
1+
# About Huff
22

33
Huff is a low-level programming language designed for developing highly optimized smart contracts that run on the Ethereum Virtual Machine (EVM). Huff does not hide the inner workings of the EVM and instead exposes its programming stack to the developer for manual manipulation.
44

55
While EVM experts can use Huff to write highly-efficient smart contracts for use in production, it can also serve as a way for beginners to learn more about the EVM.
66

77
If you're looking for an in-depth guide on how to write and understand Huff, check out the [tutorials](../tutorial/overview.md).
88

9-
## There is `huff-rs` and `huff-neo`?
10-
11-
Yes, there are two versions of the Huff compiler. The original compiler, `huff-rs` is no longer maintained. There is a plan to revive it as [huff2](https://github.com/huff-language/huff2), but since it is a new development from scratch, it is unknown when it will have feature parity with the original compiler. `huff-neo` tries to step-in and continues the development and also tries to evolve the Huff language where necessary.
12-
13-
149
## History of the Huff Language
1510
The [Aztec Protocol](https://aztec.network/) team originally created Huff to write [Weierstrudel](https://github.com/aztecprotocol/weierstrudel/tree/master/huff_modules), an on-chain elliptical curve arithmetic library that requires incredibly optimized code that neither [Solidity](https://docs.soliditylang.org/) nor [Yul](https://docs.soliditylang.org/en/latest/yul.html) could provide.
1611

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Comparison to huffc
2+
The goal of `huff-neo` is to keep the same syntax as `huffc` but to be more efficient and to have a better error handling. There are some additions to the language but the syntax should be backwards compatible.
3+
4+
## There is `huff-rs` and `huff-neo`?
5+
6+
Yes, there are two versions of the Huff compiler. The original compiler, `huff-rs` is no longer maintained. There is a plan to revive it as [huff2](https://github.com/huff-language/huff2), but since it is a new development from scratch, it is unknown when it will have feature parity with the original compiler. `huff-neo` tries to step-in and continues the development and also tries to evolve the Huff language where necessary.
7+
8+
## New in `huff-neo`
9+
There are some new features in `huff-neo` that are not available in `huffc`.
10+
11+
### Allowed use of built-in functions for constants and code tables
12+
The usage of built-in functions for constants and code tables is now possible.
13+
14+
```javascript
15+
#define constant FUNC_TEST = __FUNC_SIG("test(uint256)")
16+
#define constant BYTES_HELLO = __BYTES("hello")
17+
18+
#define code_table TEST_TABLE {
19+
0x123
20+
__FUNC_SIG("test(uint256)")
21+
__BYTES("hello")
22+
__LEFTPAD(__FUNC_SIG("test(uint256)")) // New built-in function __LEFTPAD
23+
[FUNC_TEST]
24+
[BYTES_HELLO]
25+
}
26+
```
27+
28+
### New built-in functions
29+
There are new built-in functions available in `huff-neo`.
30+
31+
- `__LEFTPAD` - Left pads a hex input or the result of a passed built-in in a code table.
32+
- `__BYTES` - Converts a string to the UTF-8 representation bytes and pushes it to the stack.
33+
34+
```javascript
35+
#define macro MAIN() = takes (0) returns (0) {
36+
__BYTES("hello") // Will push UTF-8 encoded string (PUSH5 0x68656c6c6f)
37+
}
38+
```
39+
40+
### New test capabilities
41+
The test module has been refactored to use `anvil` and `forge` features from `foundry` to fork the mainnet. This allows for more advanced testing capabilities.
42+
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ Now, with `hnc-up` installed and in your path, you can simply run `hnc-up` to in
1616

1717
### On Windows, build from the source
1818

19-
If you use Windows, you need to build from the source to get huff.
19+
If you use Windows, you can build from the source or download the binary form the [releases](https://github.com/cakevm/huff-neo/releases) to get huff.
2020

21+
#### Building from the source
2122
Download and run `rustup-init` from [rustup.rs](https://win.rustup.rs/x86_64). It will start the installation in a console.
2223

2324
If you encounter an error, it is most likely the case that you do not have the VS Code Installer which you can [download here](https://visualstudio.microsoft.com/downloads/) and install.

book/huff-language/builtin-functions.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,26 @@ At compile time, the invocation of `__EVENT_HASH` is substituted with `PUSH32 ev
1212
### `__ERROR(<error definition>)`
1313
At compile time, the invocation of `__ERROR` is substituted with `PUSH32 error_selector`, where `error_selector` is the left-padded 4 byte error selector of the passed error definition.
1414

15+
### `__LEFTPAD(<string>|<hex>|<builtin function>)`
16+
At compile time, the invocation of `__LEFTPAD` is substituted with `padded_literal`, where `padded_literal` is the left padded version of the passed input. This function is only available as constant assignment or in a code table.
17+
18+
#### Example
19+
```plaintext
20+
__LEFTPAD(0x123)
21+
// will result in 32 bytes:
22+
0x0000000000000000000000000000000000000000000000000000000000000123
23+
```
24+
1525
### `__RIGHTPAD(<string>|<hex>|<builtin function>)`
1626
At compile time, the invocation of `__RIGHTPAD` is substituted with `PUSH32 padded_literal`, where `padded_literal` is the right padded version of the passed input.
1727

28+
#### Example
29+
```plaintext
30+
__RIGHTPAD(0x123)
31+
// will result in 32 bytes:
32+
0x1230000000000000000000000000000000000000000000000000000000000000
33+
```
34+
1835
### `__codesize(<macro>|<function>)`
1936
Pushes the code size of the macro or function passed to the stack.
2037

@@ -27,6 +44,13 @@ This function is used to insert raw hex data into the compiled bytecode. It is u
2744
### `__BYTES(<string>)`
2845
This function allows to insert a string as UTF-8 encoded bytes into the compiled bytecode. The resulting bytecode is limited to 32 bytes.
2946

47+
#### Example
48+
```javascript
49+
#define macro MAIN() = takes (0) returns (0) {
50+
__BYTES("hello") // Will push UTF-8 encoded string (PUSH5 0x68656c6c6f)
51+
}
52+
```
53+
3054
## Combining Builtin Functions
3155
Some builtin functions can be combined with other functions. Possible combinations are:
3256
- `__RIGHTPAD(__FUNC_SIG("test(address, uint256)"))`

book/huff-language/code-table.md

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,38 @@ them at the end of the runtime bytecode, assuming they are referenced
55
somewhere within the contract.
66

77
## Example
8+
9+
### Define a code table
810
```javascript
911
#define table CODE_TABLE {
1012
0x604260005260206000F3
1113
}
14+
15+
#define macro MAIN() = takes (0) returns (0) {
16+
17+
// Copy the code table into memory at 0x00
18+
__tablesize(CODE_TABLE) // size
19+
__tablestart(CODE_TABLE) // offset
20+
0x00 // destOffset
21+
codecopy
22+
}
1223
```
1324

14-
Usage of a builtin function inside a code table:
25+
### Usage of a builtin function
1526
```javascript
1627
#define table CODE_TABLE {
1728
__RIGHTPAD(__FUNC_SIG("test(address, uint256)"))
1829
0x604260005260206000F3
1930
}
20-
```
31+
```
32+
33+
### Usage of a constant reference
34+
```javascript
35+
#define constant CONST = 0x123
36+
37+
#define table CODE_TABLE {
38+
[CONST]
39+
__LEFTPAD([CONST])
40+
}
41+
```
42+

book/huff-language/constants.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Constants in Huff contracts are not included in the contract's storage; Instead,
44
they are able to be called within the contract at compile time. Constants
5-
can either be bytes (32 max) or a `FREE_STORAGE_POINTER`. A `FREE_STORAGE_POINTER`
5+
can either be bytes (32 max), `FREE_STORAGE_POINTER` or a built-in function. A `FREE_STORAGE_POINTER`
66
constant will always represent an unused storage slot in the contract.
77

88
In order to push a constant to the stack, use bracket notation: `[CONSTANT]`
@@ -14,6 +14,7 @@ In order to push a constant to the stack, use bracket notation: `[CONSTANT]`
1414
#define constant NUM = 0x420
1515
#define constant HELLO_WORLD = 0x48656c6c6f2c20576f726c6421
1616
#define constant FREE_STORAGE = FREE_STORAGE_POINTER()
17+
#define constant TEST = __FUNC_SIG("test(uint256)")
1718
```
1819

1920
**Constant Usage**

book/tutorial/the-basics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Installation
44

5-
Before you get started writing Huff you will have to install the compiler. Head over to [Getting Started](../get-started/overview.md) and follow the steps to get it installed.
5+
Before you get started writing Huff you will have to install the compiler. Head over to [Getting Started](../get-started/getting-started.md) and follow the steps to get it installed.
66
Once complete - come back here!!
77

88
## What you are going to learn?

crates/codegen/src/irgen/arg_calls.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::Codegen;
12
use huff_neo_utils::ast::span::AstSpan;
23
use huff_neo_utils::prelude::*;
34
use std::str::FromStr;
@@ -9,6 +10,7 @@ use std::str::FromStr;
910
/// Arg Call Bubbling
1011
#[allow(clippy::too_many_arguments)]
1112
pub fn bubble_arg_call(
13+
evm_version: &EVMVersion,
1214
arg_name: &str,
1315
bytes: &mut Vec<(usize, Bytes)>,
1416
macro_def: &MacroDefinition,
@@ -64,6 +66,7 @@ pub fn bubble_arg_call(
6466
let ac_ = &ac.to_string();
6567
return if last_mi.1.macro_name.eq(&macro_def.name) {
6668
bubble_arg_call(
69+
evm_version,
6770
ac_,
6871
bytes,
6972
bubbled_macro_invocation,
@@ -74,7 +77,7 @@ pub fn bubble_arg_call(
7477
jump_table,
7578
)
7679
} else {
77-
bubble_arg_call(ac_, bytes, bubbled_macro_invocation, contract, new_scope, offset, mis, jump_table)
80+
bubble_arg_call(evm_version, ac_, bytes, bubbled_macro_invocation, contract, new_scope, offset, mis, jump_table)
7881
};
7982
}
8083
MacroArg::Ident(iden) => {
@@ -98,6 +101,9 @@ pub fn bubble_arg_call(
98101
let hex_literal: String = bytes32_to_hex_string(sp, false);
99102
format!("{:02x}{hex_literal}", 95 + hex_literal.len() / 2)
100103
}
104+
ConstVal::BuiltinFunctionCall(bf) => {
105+
Codegen::gen_builtin_bytecode(evm_version, contract, bf, macro_invoc.1.span.clone())?
106+
}
101107
ConstVal::FreeStoragePointer(fsp) => {
102108
// If this is reached in codegen stage,
103109
// `derive_storage_pointers`

0 commit comments

Comments
 (0)