Builtin Functions

Several builtin functions are provided by the Huff compiler. The functions can be used inside a macro, function definition to generate the desired bytecode. The usage of __RIGHTPAD, __FUNC_SIG and __BYTES is usable in a data table. The builtin functions are evaluated at compile time and substituted with the corresponding bytecode.

__FUNC_SIG(<string>|<function definition>)

At compile time, the invocation of __FUNC_SIG is substituted with PUSH4 function_selector, where function_selector is the 4 byte function selector of the passed function definition or string. If a string is passed, it must represent a valid function signature i.e. "test(address, uint256)"

__EVENT_HASH(<string>|<event definition>)

At compile time, the invocation of __EVENT_HASH is substituted with PUSH32 event_hash, where event_hash is the selector hash of the passed event definition or string. If a string is passed, it must represent a valid event signature i.e. "TestEvent(uint256, address indexed)"

__ERROR(<error definition>)

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.

__LEFTPAD(<string>|<hex>|<builtin function>)

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.

Example

__LEFTPAD(0x123)
// will result in 32 bytes:
0x0000000000000000000000000000000000000000000000000000000000000123

__RIGHTPAD(<string>|<hex>|<builtin function>)

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.

Example

__RIGHTPAD(0x123)
// will result in 32 bytes:
0x1230000000000000000000000000000000000000000000000000000000000000

__codesize(<macro>|<function>)

Pushes the code size of the macro or function passed to the stack.

__tablestart(<table>) and __tablesize(<table>)

These functions related to Jump Tables are described in the next section.

__VERBATIM(<hex>)

This function is used to insert raw hex data into the compiled bytecode. It is useful for inserting raw opcodes or data into the compiled bytecode.

__BYTES(<string>)

This function allows to insert a string as UTF-8 encoded bytes into the compiled bytecode. The resulting bytecode is limited to 32 bytes.

Example

#define macro MAIN() = takes (0) returns (0) {
    __BYTES("hello") // Will push UTF-8 encoded string (PUSH5 0x68656c6c6f)
}

Combining Builtin Functions

Some builtin functions can be combined with other functions. Possible combinations are:

  • __RIGHTPAD(__FUNC_SIG("test(address, uint256)"))
  • __RIGHTPAD(__BYTES("hello"))

Example

// Define a function
#define function test1(address, uint256) nonpayable returns (bool)
#define function test2(address, uint256) nonpayable returns (bool)

// Define an event
#define event TestEvent1(address, uint256)
#define event TestEvent2(address, uint256)

#define macro TEST1() = takes (0) returns (0) {
    0x00 0x00                // [address, uint]
    __EVENT_HASH(TestEvent1) // [sig, address, uint]
    0x00 0x00                // [mem_start, mem_end, sig, address, uint]
    log3                     // []
}

#define macro TEST2() = takes (0) returns (0) {
    0x00 0x00                // [address, uint]
    __EVENT_HASH(TestEvent2) // [sig, address, uint]
    0x00 0x00                // [mem_start, mem_end, sig, address, uint]
    log3                     // []
}

#define macro MAIN() = takes (0) returns (0) {
    // Identify which function is being called.
    0x00 calldataload 0xE0 shr
    dup1 __FUNC_SIG(test1) eq test1 jumpi
    dup1 __FUNC_SIG(test2) eq test2 jumpi

    // Revert if no function matches
    0x00 0x00 revert

    test1:
        TEST1()

    test2:
        TEST2()
}