Let’s write our first smart contract using Huff.
About HuffHuff 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.
The contract is a simple storage contract that has a variable of type uint256. There is a function to update the value and one to read it.
Solidity Code:
// SPDX-License-Identifier: MITIn a transaction, we basically have a calldata that is being sent to the blockchain.
Ex:
This consists of:
Now, we need to get the function_selector (starting 4 bytes) from above calldata.
But how??
RIGHT SHIFTING THE CALLDATA. (>>>>)
SHR opcode: shift given bits to the right.
But how many bits to shift?? total size-32 bytes, function_selector — 4 bytes
So, if we shift it right by 32–4 = 28 bytes (or 28 * 8 = 224 bits), we get the function selector.
The Huff code till here looks like:
#define macro MAIN() = takes(0) returns (0) {Now we got the function selector.
We’ll try to match the function_selector we got with different function selectors we have here (setValue() and getValue()).
Function_selectors:
cast sig "setValue(uint256)"setValue(uint256) -> 0x55241077
getValue() -> 0x20965255
So, we’ll match the function selector obtained from calldata with the above two and call the matched function.
We can define interfaces in Huff in the following way:
/*Huff interfaces*/Let’s use the above defined function selectors to try match them with the one obtained from the calldata.
/* Huff interfaces */So, if the function selector from calldata matches with that of “setValue(uint256)”, the program counter should jump to setValue() function and it should be executed. Else it will check for “getValue()” and read the value. If no option matches, it should revert.
#define macro MAIN() = takes(0) returns(0) {Also, if any of the function selector matches, we need to skip the order of instructions and jump to that function. Let’s write the case to check for “readValue” function.
#define macro MAIN() = takes(0) returns(0) {If no function selector matches with the one from the calldata, it should revert. We can use revert opcode to halt execution and reverting any state changes made.
The code till now looks like:
/*Huff interfaces*/Now let’s try to understand what would happen if the function selector matches with that of setValue().
When SET_VALUE macro is called, it should take the input value and update the variable. But how does it update the storage?
We have something called as FREE_STORAGE_POINTER() that points to currently available storage slot.
#define constant VALUE_STORAGE_SLOT = FREE_STORAGE_POINTER();Now let’s see how getValue() works. To read a value:
Final Code:
#define function setValue(uint256) nonpayable returns()Github: https://github.com/dheerajkumardk/horseStore
Writing Smart Contract using Huff was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.
All Rights Reserved. Copyright , Central Coast Communications, Inc.