# Walkthrough: Huff Challenge #5

By [PraneshASP ⚡](https://paragraph.com/@praneshasp) · 2023-07-13

---

In this article, we’re going to have a look into the solution for [Huff Challenge #5](https://twitter.com/huff_language/status/1586401774927126528). If you wanna check-out the solutions for other challenges, look [here](https://mirror.xyz/0xF314e9Cc3D5F382669eeB01d31f421aF931b9eBB).

The Challenge:
==============

The challenge we're examining today revolves around message signatures. Our goal is to create a contract using Huff, that takes a signature as input from the calldata, verifies if the message was indeed signed by the sender of the transaction, and returns true if it was. If the message wasn't signed by the sender or if the calldata doesn't adhere to the expected structure, we want the contract to do something that causes the transaction to run out of gas.

Solution:
=========

Here’s the solution for your quick glance:

    #define macro MAIN() = takes (0) returns (0) {
        /// Check if calldatasize is 97 bytes (MessageHash=32, Signature=65)
        calldatasize 
        0x61 eq 
        extractParamsAndStore jumpi
    
        oog jump
            
        extractParamsAndStore:
        /// Store the message hash
        0x00 calldataload
        0x00 mstore
    
        /// Store 'v'
        0x60 calldataload
        0x3f mstore
    
        /// Store 'r'
        0x20 calldataload
        0x40 mstore 
        
        /// Store 's'
        0x40 calldataload
        0x60 mstore 
        
        /// Prepare stack for 'ecrecover' staticcall 
        0x20 
        0x00 
        0x80 
        0x00 
        chainid 
        gas
        staticcall validate jumpi
    
        oog jump
    
        /// Check if caller==retdata (signer address)
        validate:
        0x00 mload 
        dup1
        caller 
        eq valid jumpi
    
        oog jump
    
        // Return true
        valid: 
        chainid 
        0x00 mstore
        0x20 0x00 return
    
        // out-of-gas
        oog:
        0x01 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff mstore
    

If the above code is all Greek and Latin to you, don’t worry. I’m here to break it down for you.

    #define macro MAIN() = takes (0) returns (0) {
        calldatasize 
        0x61 eq 
        extractParamsAndStore jumpi
    
        oog jump
    

The first part of the contract is responsible for checking whether the `calldatasize` equals `0x61` (which is the hexadecimal representation of `97` in decimal). `97` bytes is the expected size of the calldata (MessageHash=32 bytes, Signature=65 bytes). If the size is correct, it jumps to the `extractParamsAndStore` label. Otherwise, it jumps to the `oog` (out-of-gas) label to make the transaction run out of gas.

**_Assumption_**\*: The contract assumes that the calldata is structured in a specific way (message hash first, followed by the v, r, s components of the signature). If the input doesn't follow this structure, the contract won't function as intended.\*

Next, we extract parameters from the calldata:

      extractParamsAndStore:
        0x00 calldataload
        0x00 mstore
    
        0x60 calldataload
        0x3f mstore
    
        0x20 calldataload
        0x40 mstore 
    
        0x40 calldataload
        0x60 mstore 
    

This part of the code extracts and stores the message hash, v, r, and s values from the calldata. These values represent the signed message we're looking for. The `calldataload` operation takes the start byte from the calldata, and `mstore` stores this data in memory.

We then prepare the stack with parameters for the `ecrecover` call:

        0x20 
        0x00 
        0x80 
        0x00 
        chainid 
        gas
        staticcall validate jumpi
    
        oog jump
    

A staticcall is made to the precompiled contract residing at the address `0x01`. It implements the `ecrecover` method. It is used to extract the signer’s address from the signature using message hash, v, r, and s values as input. The `jumpi` instruction then checks the outcome of the `ecrecover` call. If it's successful, the control gets transferred to the `validate` label. Otherwise, it jumps to `oog`, causing the transaction to run out of gas.

**_Assumption_**_: The above piece of code assumes that the contract will be deployed on the Ethereum mainnet as you can see we use_ `chainid` _as the target address of static call where the precompile for_ `ecrecover` _resides. To learn more about precompiles,_ [_look here_](https://www.evm.codes/precompiled)_._

The contract then verifies if the extracted signer’s address matches the transaction sender’s address:

      validate:
        0x00 mload          // [rcvd_address]
        dup1                // [rcvd_address, rcvd_address]
        caller              // [msg.sender, rcvd_address]
        eq valid jumpi      // [msg.sender == rcvd_address?]
    
        oog jump            // if not equal, jump to out-of-gas block
    

The `mload` operation loads the signer's address from memory which is be the return value of the `ecrecover` call, `dup1` duplicates this address on the stack, and `caller` gets the address of the transaction sender. The `eq` operation checks if the two addresses match. If they do, the program jumps to the `valid` label. Otherwise, it jumps to `oog`, again causing the transaction to run out of gas.

Finally, the contract returns true in the case of a valid signature:

    valid: 
      chainid 
      0x00 mstore
      0x20 0x00 return
    

This section stores the current chain id (which serves as a boolean value _0x01_ for _Mainnet_ to represent _true_) into memory and returns it.

And in case of invalid calldata or signature, we run out of gas:

    oog:
      0x01 
      0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff            
    
      mstore
    

This code tries to store a massive value into memory, thereby using up all the available gas and causing an out-of-gas error.

* * *

**You can find a runnable PoC including tests for all the Huff Challenges here:**

[https://github.com/minaminao/ctf-blockchain/tree/main/src/HuffChallenge](https://github.com/minaminao/ctf-blockchain/tree/main/src/HuffChallenge)

**To learn more about Huff, join the Huff developers discord server:**

[https://discord.gg/p7z3DpVnT2](https://discord.gg/p7z3DpVnT2)

Stay tuned… Until next time 👋👋

---

*Originally published on [PraneshASP ⚡](https://paragraph.com/@praneshasp/walkthrough-huff-challenge-5)*
