<?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>Patrick Collins</title>
        <link>https://paragraph.com/@patrickalphac-old</link>
        <description>A web3 dev addicted to smart contracts</description>
        <lastBuildDate>Sat, 18 Jul 2026 19:52:08 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>Patrick Collins</title>
            <url>https://storage.googleapis.com/papyrus_images/b1d034bfe75f166b1f0a2bbca51dbbd445ddb2fae9477723ff26195cab961646.png</url>
            <link>https://paragraph.com/@patrickalphac-old</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Blockchain Developer | How to learn everything you need to become one]]></title>
            <link>https://paragraph.com/@patrickalphac-old/blockchain-developer-how-to-learn-everything-you-need-to-become-one</link>
            <guid>5psShRsfs8I13yED33oa</guid>
            <pubDate>Wed, 07 Jun 2023 14:01:42 GMT</pubDate>
            <description><![CDATA[You can learn everything you need about solidity, smart contract development, and becoming a blockchain developer with Patrick Collins’ latest course.Patrick CollinsLearn Solidity, Blockchain Development, and more For the past three years, every year, I’ve made an end-to-end data dump, passion project, web3 education course of what I think the minimum knowledge a blockchain engineer needs to have to be. And we did it again this year, using the Foundry framework, and we are just getting starte...]]></description>
            <content:encoded><![CDATA[<h2 id="h-you-can-learn-everything-you-need-about-solidity-smart-contract-development-and-becoming-a-blockchain-developer-with-patrick-collins-latest-course" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">You can learn everything you need about solidity, smart contract development, and becoming a blockchain developer with Patrick Collins’ latest course.</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/04c55924ce4a7ee549def9e0e94102fc44cab5207c73721d8a3245ad825a8a9b.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><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cc0e26df1da84673b410d1a895fcc2b7b30df602da6b6de888c5e807e1efe231.png" alt="Patrick Collins" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Patrick Collins</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6470b3ea166fdd35c8fba8a69ef4b7d22e0d7122b0babd420b95362178bec4c3.webp" 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>Learn Solidity, Blockchain Development, and more</p><p>For the past three years, every year, I’ve made an end-to-end data dump, passion project, web3 education course of what I think the minimum knowledge a blockchain engineer needs to have to be.</p><p>And we did it again this year, using the Foundry framework, and we are just getting started.</p><p>This is easily the most advanced, beginner-to-hero course on solidity and blockchain development ever created. Veterans and new developers will likely find new ways to code by taking this course!</p><p>From doing all these courses, we decided it would be best to put all our learnings into text, and we are working on an education site <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://web3education.dev/">Web3Education.dev</a>, to include everything. So be sure to subscribe there to know when the website is finally live!</p><p>Video 1 of 3 here 👇</p><h2 id="h-why-foundry" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why Foundry</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/15808031c5dd1effc7c8f49198a338835124cd9755ee282ee2b193c831cb6cec.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://book.getfoundry.sh/">https://book.getfoundry.sh/</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://book.getfoundry.sh/">Foundry</a> is quickly becoming the #1 smart contract development framework and for good reason.</p><ul><li><p>It’s 100% solidity based, meaning you don’t need to learn another language as you’re creating your smart contracts</p></li><li><p>It’s the fastest framework out there, being up to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.paradigm.xyz/2021/12/introducing-the-foundry-ethereum-development-toolbox#how-fast">20x faster</a> than other frameworks</p></li><li><p>It’s the preferred tool by smart contract auditors due to it’s speed and reliability</p></li></ul><h2 id="h-past-courses" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Past Courses</h2><p>I’ve made two courses in the past:</p><ul><li><br></li><li><br></li></ul><p>These two courses will teach you everything you need to know, for free. The titles are long, but you can sort of think of them as “the javascript one” and “the python one”.</p><p>This new one you can think of as “the foundry one”.</p><p>They each have code repositories associated with them — so if you want, you can just go through all the code! The <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/smartcontractkit/full-blockchain-solidity-course-py">python one is here</a>, and the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/smartcontractkit/full-blockchain-solidity-course-js">javascript one is here</a>.</p><h2 id="h-which-one-should-i-take" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Which one should I take?</h2><p>Summary: Pick the Javascript one or the Foundry one.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4f79143e8c648ea35ea2178d7f9ac1907a0ddf7b7f9780b8cab8e1685715dda4.webp" 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>The one that started it all</p><p><strong>If you want the most up-to-date -&gt; Pick the Foundry one.</strong></p><p><strong>If you want to learn full stack and you like Javascript -&gt; Pick the Javascript one.</strong></p><p>**Pretty soon, we will be deprecating the Python one. **Why?1. It’s the oldest one</p><p>2. We are working on a new Python one!</p><p>Video is difficult to keep up to date, and takes a lot of effort from myself and my team. This is another reason we are working on the education site, so it’s easier to keep all the content up to date.</p><p>The Javascript one is still up to date! With Hardhat being one of the most widely used frameworks on the planet. The only downside is Lesson 15 has to be skipped, as much of the tooling used for that lesson is no longer supported.</p><p>The rest of the javascript course is still 100% fantastic!</p><h2 id="h-what-they-all-teach" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What They All Teach</h2><p>These courses will give you the fundamentals to become a professional, smart contract / web3 / blockchain developer. They teach:</p><ul><li><p>Core fundamentals of how blockchains work and why smart contracts are important</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/v0.8.14/">Solidity</a> Fundamentals — the primary language used to write smart contracts</p></li><li><p>Work with protocols and tools like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://chain.link/">Chainlink</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/">Ethereum</a>, &amp; <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.openzeppelin.com/">Openzeppelin</a></p></li><li><p>How to create customized NFTs and ERC20 tokens</p></li><li><p>Testing, tooling, and common smart contract design patterns</p></li><li><p>Upgradeability and advanced concepts like proxies</p></li><li><p>DeFi and protocols like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://aave.com/">Aave</a></p></li><li><p>Everything you need to know about “backend” smart contract development.</p></li></ul><p>And at the end of the day, it doesn’t matter which one you pick! They are both fantastic for learning blockchain development.</p><h2 id="h-the-javascript-one" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Javascript One</h2><p>The JS one uses Hardhat tooling in the ecosystem like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/">Hardhat</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.ethers.io/v5/">Ethersjs</a>, and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/MoralisWeb3/react-moralis">react-moralis</a>. There is a lot more “stuff” in this 30+ hour edition than the python one, like:</p><ul><li><p>How to programmatically build a DAO</p></li><li><p>More lower-level explainers such as storage, <code>delegatecall</code>, and encoding</p></li><li><p>A TON of optional Front End Web3 development with <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://reactjs.org/">ReactJS</a> &amp; <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nextjs.org/">NextJS</a></p></li><li><p>Event Indexing and services with <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com/">The Graph</a> &amp; <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://moralis.io/">Moralis</a></p></li></ul><p>The javascript one is great for people with zero to a little bit of blockchain engineering experience and is the right choice if:</p><ul><li><p>You are totally new to engineering or blockchain</p></li><li><p>Or you like javascript</p></li><li><p>Or you want to use the same tools as the most popular billion-dollar defi protocols</p></li><li><p>Or you want to learn how to build websites that use smart contracts</p></li><li><p>You want the longest most in-depth video of blockchain education content ever created</p></li></ul><h2 id="h-summary" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Summary</h2><p><strong>If you want the most up-to-date -&gt; Pick the Foundry one.</strong></p><p><strong>If you want to learn full stack and you like Javascript -&gt; Pick the Javascript one.</strong></p><p>Pick one.</p><p>Start learning.</p><p>It doesn’t really matter.</p><p>And have fun.</p><p>What’s most important is you take the first step.</p><p>When you’re done, and you’re looking for the next steps, be sure to watch my video on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=e1N4aWIJMN0">how to become a blockchain engineer</a>, it’ll give you some steps on where to go next.</p><p>Happy learning!</p>]]></content:encoded>
            <author>patrickalphac-old@newsletter.paragraph.com (Patrick Collins)</author>
        </item>
        <item>
            <title><![CDATA[Formal Verification & Symbolic Execution | The Security Silver Bullet?]]></title>
            <link>https://paragraph.com/@patrickalphac-old/formal-verification-symbolic-execution-the-security-silver-bullet</link>
            <guid>wHXrWfXk58wSI4XxztSe</guid>
            <pubDate>Wed, 26 Apr 2023 00:02:05 GMT</pubDate>
            <description><![CDATA[We look at formal verification & symbolic execution with two Trail of Bits Web3 security team members. Additionally, we review the value these techniques bring and compare them to other tools.Formal Verification w/ Trail Of Bits A huge thank you to Trail of Bits Troy & Josselin for taking the time on this interview. Additionally, special thanks to Hari, Runtime Verification, Leo Alt, and Palina for their help in understanding these concepts and work in the field. You can see the full intervie...]]></description>
            <content:encoded><![CDATA[<h2 id="h-we-look-at-formal-verification-and-symbolic-execution-with-two-trail-of-bits-web3-security-team-members-additionally-we-review-the-value-these-techniques-bring-and-compare-them-to-other-tools" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">We look at formal verification &amp; symbolic execution with two Trail of Bits Web3 security team members. Additionally, we review the value these techniques bring and compare them to other tools.</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/28eb07df59bc280cec798b317768f61d071b95fb6b946735bf40397d6c1c1cce.webp" 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>Formal Verification w/ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trailofbits.com/">Trail Of Bits</a></p><p><em>A huge thank you to Trail of Bits </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/0xalpharush"><em>Troy</em></a> &amp; <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Montyly"><em>Josselin</em></a> for taking the time on this interview. Additionally, special thanks to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/_hrkrshnn"><em>Hari</em></a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/rv_inc"><em>Runtime Verification</em></a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/leonardoalt"><em>Leo Alt</em></a>, and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/palinatolmach"><em>Palina</em></a> for their help in understanding these concepts and work in the field.</p><p><em>You can see the full interview </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=H52U4ibkf5Q"><em>with Troy</em></a> here.</p><p><em>You can see the full interview </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=3pWYvtx_sjA"><em>with Josselin</em></a> here.</p><h2 id="h-introduction" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Introduction</h2><p>Watch the video here</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Formal_verification">Formal verification</a> is the act of proving or disproving a given property of a system using a mathematical model.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Symbolic_execution">Symbolic execution</a> is one technique used for formal verification. Symbolic execution explores the different paths in a program, creating a mathematical representation for each path.</p><p>Plainly stated, symbolic execution is converting your code to a set of mathematical expressions. Or even more plainly, making your code math.</p><p>Is this the silver bullet for your auditing journey? Let’s find out.</p><h2 id="h-the-team" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Team</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/94e3f8930021b3500f2b8746a94918de6024b173c02adbef3999a6eeb72def64.webp" 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>Josselin interview thumbnail</p><p>I had the absolute pleasure of interviewing Trail of Bits head of blockchain engineering, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Montyly">Josselin</a> and security engineer from Trail of Bits, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/0xalpharush">Troy</a>, about testing methodologies and formal verification. I have links to the full interviews with both of them (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=H52U4ibkf5Q">Troy</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=3pWYvtx_sjA">Josselin</a>) if you’d like to watch!</p><p>To understand what formal verification and symbolic execution actually are we need a quick refresher on some of testing in Web3. If you haven’t seen my <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=juyY-CTolac">invariant testing video</a>, be sure to watch that first before reading this.</p><p>When testing, what tools do we use to have high assurance that our program works the way we want it?</p><h2 id="h-layer-0or-manual-review" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Layer 0| Manual Review</h2><p>Every auditor and smart contract engineer should be able to manually review their own code. ChatGPT isn’t good enough. Manual review is great, but we need to make sure we don’t rely purely on humans for results, we need to have automated processes so we can have more assurance that bugs are found.</p><h2 id="h-layer-1-or-unit-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Layer 1 | Unit Test</h2><p>Obviously, you have unit tests, which test a very specific thing. Having a unit test for every line of your code will give you good <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.atlassian.com/continuous-delivery/software-testing/code-coverage">code coverage</a>. And it’s the bare minimum for testing.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/02abb22425805ad0bff0473d88748e6f2ba44faaa20859cd27d6903d92decc7c.webp" 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>Example Solidity Function</p><p>For example, if the above is our solidity, and our <code>setNumber</code>function should set <code>number</code> to <code>newNumber</code>. A unit test would be able to catch this.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/06d5c9f25d8df9af5e0273e33256e7c79e118dff0d999c251a1fa4a1c6012cf6.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://getfoundry.sh/">Foundry</a> unit test output</p><p>And if we’re using <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://getfoundry.sh/">Foundry</a>, we could get an output that looks like the above.</p><p>If a test fails, this means that our test caught an issue, and we can go back into our code to fix.</p><p>Most frameworks like Foundry, Hardhat, Apeworx, Truffle, and Brownie all have unit testing capability.</p><h2 id="h-layer-2or-fuzz-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Layer 2| Fuzz Test</h2><blockquote><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://patrickalphac.medium.com/fuzz-invariant-tests-the-new-bare-minimum-for-smart-contract-security-87ebe150e88c">Fuzzing</a> is where you take random inputs and run them through your program. So you have to define things in your code that you always want to hold true.</p><p>— <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/0xalpharush">Troy</a></p></blockquote><p>Fuzz testing is the new bare minimum for Web3 security.</p><p>Cuz I say so.</p><p>If you haven’t watched my video on fuzzing… Do it!</p><p>For fuzzing/invariant/property tests, you need to understand the property or invariant of your system to do fuzzing. Once you have your property defined, you throw random data at your system to break that property. If you find something that breaks it, you know you have an edge case that you need to refactor your code to handle.</p><p>Foundry, Echidna, and Consensys Diligence all have fuzzers.</p><h2 id="h-layer-3-or-static-analysis" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Layer 3 | Static Analysis</h2><blockquote><p>Unit testing and fuzz testing are known as dynamic testing. Dynamic means that you’re actually doing something, like actually running our code.</p><p>- Troy</p></blockquote><p>In static analysis, we just look at our code or have some tool look at our code. For example, this code here has a classic reentrancy vulnerability in our withdrawal function.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9618a20d95b93c52610a6019a1e386975ee1d08557896bc4d533bcd937681ff8.webp" 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>Vulnerable Code</p><p>If we run a static analysis tool like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/crytic/slither">Slither</a>, it’ll automatically detect this error. This is great for very quickly picking out very specific parts of your code that are known to be bad practices.</p><p>Even the Solidity compiler could be considered a static analysis tool.</p><h2 id="h-layer-4-or-formal-verification" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Layer 4 | Formal Verification</h2><blockquote><p>Formal verification is going to be the act of proving or disproving a given property of the system. This is usually done through a mathematical model of the system and the <strong>property</strong>.</p><p>— <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Montyly">Josselin</a></p></blockquote><p>There’s that word again, property. You see that almost no matter what you’re doing in your testing, you need to understand the properties of your system, and right there, Josselin gave us some of the keys between fuzz testing and formal verification.</p><ul><li><p>Fuzz testing tries to break properties by throwing random data at your system.</p></li><li><p>Formal verification tries to break properties using mathematical proofs</p></li></ul><p>There are many different ways to do formal verification such as:</p><ul><li><p>Symbolic execution</p></li><li><p>Abstract interpretation</p></li><li><p>Model Checking</p></li></ul><p>For this blog, we’re gonna focus on symbolic execution, as that’s one of the most popular ways currently done in Web3.</p><h2 id="h-symbolic-execution" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Symbolic Execution</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/542422a69409910a19ab754f898371a47b91d5753f017f17a24d093eeaa31fc1.webp" 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>Example of path exploration</p><p>You can learn more about symbolic execution in general from <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=yRVZPvHYHzw">this MIT video</a>.</p><p>Symbolic execution is a technique where you try to explore the different paths of the program and represent those paths as mathematical expressions to try to prove something. For every execution path, you’re going to create a mathematical representation. So, the first thing we need to do is figure out what we wanna prove or disprove.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/742aceb1d30ab89aa7e7bc58716948e661096a8378032865b5aae286640bbb02.webp" 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>Sample Code</p><p>For our demo above, let’s say our invariant is that <code>f</code> should never revert, and that’s what we’re going to try to prove or disprove. Now, this might seem like a silly example, but you can imagine that this was a function called withdraw money, and you want users to always be able to get their money out. Which would seem like a much less silly example.</p><p>In symbolic execution, we’re going to convert this function to a mathematical/logical representation of every execution path from our code. Once we have a set of math functions, we can push those into a solver, which will tell us if a property is true or false, or if our invariant is true or false. To use symbolic execution for formal verification, we follow these steps:</p><ol><li><p>Explore all possible paths</p></li><li><p>Convert paths to mathematical expressions</p></li><li><p>Send mathematical expressions into a SMT/SAT Solver</p></li></ol><h2 id="h-exploring-the-paths" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Exploring the paths</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9199ccd6fcf05cf1dd2d9a9901fedcb686c21f462adf20a47890f04d131c74ef.webp" 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>Visual of the process of formal verification with Symbolic Execution</p><p>In this example, we have 2 paths:</p><ul><li><p>Path 1: We return (a + 1)</p></li><li><p>Path 2: a + 1 overflows and we revert</p></li></ul><p>If we pass the max <code>uint256</code> value, and try to add 1 to it, solidity will revert (as of solidity 0.8). These are the two possible paths our code can take. Software tools can find these automatically, but we will show you those later.</p><p>Now that we have our 2 paths, we convert them to mathematical expressions. One of the most popular set of expressions is to convert them to a set of booleans, like so:</p><h2 id="h-path-1" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Path 1</h2><ul><li><p><code>a &lt; type(uint256).max</code></p></li></ul><h2 id="h-path-2" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Path 2</h2><ul><li><p><code>a == type(uint256).max</code></p></li><li><p><code>a + 1 &lt; a</code></p></li></ul><p><code>Path 2</code> can only be achieved if <code>a &gt; a + 1</code> since we revert when 1 is added to <code>a</code>. This set of booleans will then be placed into a SAT solver, which will try to find values for <code>a</code> to make all the booleans true. If it is able to find a value for <code>a</code> , it will consider the group of booleans “solvable” or <code>sat</code> .</p><p>With our small example, you can see how it’s easy to make a group of booleans, but if we get more complex functions, it gets harder. We want to convert this list of booleans to a SMT-LIB language to give to a sat solver, the above example, could be re-written in SMTLIB as such:</p><pre data-type="codeBlock" text="; Declare a symbolic integer variable &apos;a&apos; as a 256-bit integer
(declare-const a (_ BitVec 256))

; Create a context for Path 1
(push)

; Add assertions for Path 1
; assert a is not equal to `uint256.max`
(assert (distinct a #xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff))
(check-sat)

; Remove the context for Path 1
(pop)

; Create a context for Path 2
(push)

; Add assertions for Path 2
; assert a is equal to `uint256.max`
(assert (= a #xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff))
; bvult is &quot;bit vector unsigned less than&quot;, so we are checking that a + 1 is less than a
(assert (bvult (bvadd a (_ bv1 256)) a))

; Check if Path 2 is satisfiable
(check-sat)
"><code>; Declare a symbolic integer variable <span class="hljs-string">'a'</span> <span class="hljs-keyword">as</span> a <span class="hljs-number">256</span><span class="hljs-operator">-</span>bit integer
(declare<span class="hljs-operator">-</span>const a (<span class="hljs-keyword">_</span> BitVec <span class="hljs-number">256</span>))

; Create a context <span class="hljs-keyword">for</span> Path <span class="hljs-number">1</span>
(push)

; Add assertions <span class="hljs-keyword">for</span> Path <span class="hljs-number">1</span>
; <span class="hljs-built_in">assert</span> a <span class="hljs-keyword">is</span> not equal to `<span class="hljs-keyword">uint256</span>.<span class="hljs-built_in">max</span>`
(<span class="hljs-built_in">assert</span> (distinct a #xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff))
(check<span class="hljs-operator">-</span>sat)

; Remove the context <span class="hljs-keyword">for</span> Path <span class="hljs-number">1</span>
(pop)

; Create a context <span class="hljs-keyword">for</span> Path <span class="hljs-number">2</span>
(push)

; Add assertions <span class="hljs-keyword">for</span> Path <span class="hljs-number">2</span>
; <span class="hljs-built_in">assert</span> a <span class="hljs-keyword">is</span> equal to `<span class="hljs-keyword">uint256</span>.<span class="hljs-built_in">max</span>`
(<span class="hljs-built_in">assert</span> (<span class="hljs-operator">=</span> a #xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff))
; bvult <span class="hljs-keyword">is</span> <span class="hljs-string">"bit vector unsigned less than"</span>, so we are checking that a <span class="hljs-operator">+</span> <span class="hljs-number">1</span> <span class="hljs-keyword">is</span> less than a
(<span class="hljs-built_in">assert</span> (bvult (bvadd a (<span class="hljs-keyword">_</span> bv1 <span class="hljs-number">256</span>)) a))

; Check <span class="hljs-keyword">if</span> Path <span class="hljs-number">2</span> <span class="hljs-keyword">is</span> satisfiable
(check<span class="hljs-operator">-</span>sat)
</code></pre><p>Now, if you take this code and paste it into a tool like Z3 or run it locally on your machine, it’ll give you an output that looks 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/4cad116848b3715ee68e9fcae457f05cd5d10e9d58579b84847fb59608d223cd.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://microsoft.github.io/z3guide/playground/Freeform%20Editing/">Z3</a> Output example</p><p>The two <code>sat</code> outputs mean they were able to find an input to make the set of booleans for each path true — and since path 2 reverts, and our invariant is that it should never revert, we proved our invariant breaks!</p><p>Now I manually created this SMTLIB code with the help of ChatGPT. However, symbolic execution tools like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/trailofbits/manticore">Manticore</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ethereum/hevm">HEVM</a>, and even the Solidity SMT checker, can give you an output like this. But all those tools come with a built-in Z3. So they’ll even just skip the step of converting to booleans and just give you the output of the SMT Solver.</p><p>If you want to see a breakdown comparing many of the tools out there doing symbolic execution, check out <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hackmd.io/@SaferMaker/EVM-Sym-Exec">this post by Palina</a>.</p><p>Even the Solidity compiler itself can do this entire process behind the scenes:</p><ul><li><p>Explore the paths</p></li><li><p>Convert the paths to a set of booleans</p></li><li><p>Check to see if those paths are reachable or not</p></li></ul><p>Using the solc compiler, we can run with Model Checker Engine, and we can look for an overflow.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b8fea1530f36054c4c6d7aa555d1733607f9ad5fc68b2f7f89cd0b793bb691e8.webp" 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>Example of running the solc SMT Checker</p><p>If we run this, you’ll see the Solidity Compiler was able to do symbolic execution. Now, reverts are pretty easy to find, but. We could instead look for reverted <code>asserts</code>. A does not equal one, rerun this, but instead of overflow, look for asserts.</p><p>We first would add an assert into our code</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/718efb92e94279e928221b063e99da7529f11a7243f387d5402d5dcfd0550257.webp" 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>Add an assert</p><p>Then run the solc checker looking for broken asserts (invariants).</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4300d669a41a59cba3fa964cdccb858c2262458be1cfbaf186a1b60997562621.webp" 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>Solidity assert checker</p><p>And we would see that again, it was able to find an input to break our assert mathematically.</p><h2 id="h-recap" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Recap</h2><p>So a lot of stuff just happened here. Let’s recap.</p><ol><li><p>We built some solidity.</p></li><li><p>We understood our invariant.</p></li><li><p>We used a symbolic execution tool like the built-in one in solidity to create a set of boolean expressions that represent every execution path of our code (this happened automagically)</p></li><li><p>Then we dumped them into a solver like Z3 (behind the scenes) to see if our property could be broken just by running this one function</p></li></ol><p>We go through a full walkthrough of this example in the interview with Josselin, so be sure to check that out as well if you want to learn more.</p><p>Don’t be afraid if this seems a bit complicated; be sure to ask questions and leave comments in the descriptions.</p><h2 id="h-limitations" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Limitations</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/92f5f40f9f286117e86f22eb726a0aa6b105771561c3622f359951417b64fa8a.webp" 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>Thumbnail of interview with Troy</p><p>Is this a silver bullet?</p><p>No.</p><blockquote><p>Sometimes the server might not be able to solve the question too, like if the question is too complex. We usually provide a timeout to the server just because, you know, if you have to invert a hash function, you know, good luck to do that with the server.</p><p>- Josselin</p></blockquote><p>Like any technology, these are not a one size fits all approach. Using symbolic execution can run into something called the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Path_explosion">path explosion problem</a>; where there are too many paths for a computer to explore in a reasonable amount of time and a solver would never be able to finish.</p><h2 id="h-in-practice" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">In Practice</h2><p>How practical is it to take all these steps? How hard is this to really do well?</p><blockquote><p>This technique requires significant effort to be used. You need to understand how they work, and you need to understand their limitation and how to help them, and also significant effort to be maintained at the end of the day. I think what really matters are the properties. If you want to know if a bug can occur and if the property can be broken, you don’t necessarily need formal method for that and you can use a fuzzer, which is way easier to use and provide like kind of the same type of value.</p><p>- Josselin</p></blockquote><p>The Trail of Bits team has created <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://secure-contracts.com/">secure-contracts.com</a> to help developers understand properties so they can build and test code in a property-based testing way.</p><p>Sometimes a sufficiently powerful fuzzer is all you need, and symbolic execution and formal verification is overkill.</p><p>Additionally, **even formal verification doesn’t prove your code is bug-free. **All it does is mathematically prove your code does that one specific thing correctly.</p><p>I’m hoping as AI takes off doing a lot of this will become much easier and I guess we’ll have to see.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>But for now, hopefully, you learned at least the basics of symbol execution. If you’d like to learn more, leave a comment and a clap.</p><p>😸😸Follow Patrick!😸😸</p><p>Book a smart contract audit: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/">Cyfrin</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/@PatrickAlphaC/videos">https://www.youtube.com/@PatrickAlphaC/videos</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/patrickalphac">https://twitter.com/patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/@patrickalphac">https://medium.com/@patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.tiktok.com/@patrickalphac">https://www.tiktok.com/@patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/channel/UCMHHNgcezTnfrJUM1vIiZlQ">https://www.youtube.com/channel/UCMHHNgcezTnfrJUM1vIiZlQ</a></p>]]></content:encoded>
            <author>patrickalphac-old@newsletter.paragraph.com (Patrick Collins)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/7c2386d751c875096856937bbb1a06f3260f4d5759a1dc36d9e969c6987ed379.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Fuzz / Invariant Tests | The New Bare Minimum For Smart Contract Security]]></title>
            <link>https://paragraph.com/@patrickalphac-old/fuzz-invariant-tests-the-new-bare-minimum-for-smart-contract-security</link>
            <guid>W0Ur01OcOUE9fM92LpWX</guid>
            <pubDate>Thu, 13 Apr 2023 22:24:12 GMT</pubDate>
            <description><![CDATA[What is fuzz testing? What are invariant tests? We introduce how to use these tools in Web3 & Solidity and explain why they are essential, especially for security. Every project should have stateful fuzz tests moving forward, and auditors can use understanding invariants to find critical bugs before code is deployed.Shout-out to Trail of Bits and Horsefacts for all the fuzzing content.IntroductionMost of the time, hacks come from scenarios you didn’t think about and write a test for. What if ...]]></description>
            <content:encoded><![CDATA[<h2 id="h-what-is-fuzz-testing-what-are-invariant-tests-we-introduce-how-to-use-these-tools-in-web3-and-solidity-and-explain-why-they-are-essential-especially-for-security-every-project-should-have-stateful-fuzz-tests-moving-forward-and-auditors-can-use-understanding-invariants-to-find-critical-bugs-before-code-is-deployed" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What is fuzz testing? What are invariant tests? We introduce how to use these tools in Web3 &amp; Solidity and explain why they are essential, especially for security. Every project should have stateful fuzz tests moving forward, and auditors can use understanding invariants to find critical bugs before code is deployed.</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/43b133a3e2525863a741d32390db1b75deb592a1220890660ad2606592c61b61.webp" 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><em>Shout-out to </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trailofbits.com/"><em>Trail of Bits</em></a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/eth_call"><em>Horsefacts</em></a> for all the fuzzing content.</p><h2 id="h-introduction" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Introduction</h2><p>Most of the time, hacks come from scenarios you didn’t think about and write a test for.</p><p>What if I told you that you could write one test that would check for almost every possible scenario?</p><p>Let’s get froggy.</p><p>As always, you can watch my video on this subject and view a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PatrickAlphaC/fuzzing-example">full sample repo here</a>.</p><div data-type="youtube" videoId="juyY-CTolac">
      <div class="youtube-player" data-id="juyY-CTolac" style="background-image: url('https://i.ytimg.com/vi/juyY-CTolac/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=juyY-CTolac">
          <img src="{{DOMAIN}}/editor/youtube/play.png" class="play"/>
        </a>
      </div></div><h2 id="h-basic-of-fuzzing" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Basic of Fuzzing</h2><h2 id="h-what-is-a-fuzz-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What is a Fuzz Test?</h2><p>Fuzz Testing or <em>Fuzzing</em> is when you supply random data to your system in an attempt to break it.</p><p>For example, if this balloon is our system/code, it would involve doing random stuff to the balloon to break it.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c351b4ad2ea3901f632cae2e12798e9444c542d7be7329bc1ae453b95a9884e2.gif" 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>Doing random stuff to a balloon — example of fuzz testing</p><p>Now, why would we want to do all that?</p><p>Let’s look at an example.</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MyContract {
    uint256 public shouldAlwaysBeZero = 0;

    uint256 private hiddenValue = 0;

    function doStuff(uint256 data) public {
        if (data == 2) {
            shouldAlwaysBeZero = 1;
        }
        if (hiddenValue == 7) {
            shouldAlwaysBeZero = 1;
        }
        hiddenValue = data;
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyContract</span> </span>{
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> shouldAlwaysBeZero <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;

    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">private</span> hiddenValue <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">doStuff</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> data</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">if</span> (data <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">2</span>) {
            shouldAlwaysBeZero <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
        }
        <span class="hljs-keyword">if</span> (hiddenValue <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">7</span>) {
            shouldAlwaysBeZero <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
        }
        hiddenValue <span class="hljs-operator">=</span> data;
    }
}
</code></pre><p>Let’s say we have this function named <code>doStuff</code>, which takes an integer as input. We additionally have a variable named <code>shouldAlwaysBeZero</code> that we want always to be zero.</p><p>The fact that this variable should always be zero is known as our <strong>invariant</strong>, or “property of the system that should always hold.”</p><blockquote><p>Invariant: The property of the system that should always hold.</p></blockquote><p>Our invariant (also known as <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/crytic/properties">property</a>) in this contract is that:</p><pre data-type="codeBlock" text="Invariant: `shouldAlwaysBeZero` MUST always be 0
"><code>Invariant: <span class="hljs-string">`shouldAlwaysBeZero`</span> MUST always be <span class="hljs-number">0</span>
</code></pre><p>In our balloon example, if we market our balloon as “indestructible,” our invariant might be that “our balloon should never be able to be popped.”</p><pre data-type="codeBlock" text="Invariant: `balloon` should never be popped
"><code><span class="hljs-title class_">Invariant</span>: <span class="hljs-string">`balloon`</span> should <span class="hljs-built_in">never</span> be popped
</code></pre><p>In DeFi, a good invariant might be:</p><ul><li><p>A protocol must always be overcollateralized</p></li><li><p>A user should never be able to withdraw more money than they deposited</p></li><li><p>There can only be 1 winner of the fair lottery</p></li></ul><h2 id="h-example-in-foundry" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Example in Foundry</h2><p>Let’s look at a normal unit test in <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/foundry-rs/foundry">Foundry</a>.</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {MyContract} from &quot;../src/MyContract.sol&quot;;
import {Test} from &quot;forge-std/Test.sol&quot;;

contract MyContractTest is Test {
    MyContract exampleContract;

    function setUp() public {
        exampleContract = new MyContract();
    }

    function testIsAlwaysZeroUnit() public {
        uint256 data = 0;
        exampleContract.doStuff(data);
        assert(exampleContract.shouldAlwaysBeZero() == 0);
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-keyword">import</span> {<span class="hljs-title">MyContract</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../src/MyContract.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">Test</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"forge-std/Test.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyContractTest</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Test</span> </span>{
    MyContract exampleContract;

    <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>{
        exampleContract <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MyContract();
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testIsAlwaysZeroUnit</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint256</span> data <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        exampleContract.doStuff(data);
        <span class="hljs-built_in">assert</span>(exampleContract.shouldAlwaysBeZero() <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
    }
}
</code></pre><p>With this single-unit test <code>testIsAlwaysZeroUnit</code>, we might think our code has enough coverage, but if we look at the <code>doStuff</code>function again, we can see that if our input is 2, our variable will not be zero.</p><pre data-type="codeBlock" text="function doStuff(uint256 data) public {
        // WHAT IS THIS IF STATEMENT???
        // 👇👇👇👇👇👇
        if (data == 2) {
            shouldAlwaysBeZero = 1;
        }
        // 👆👆👆👆👆👆

        // Ignore this one for now
        if (hiddenValue == 7) {
            shouldAlwaysBeZero = 1;
        }
        hiddenValue = data;
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">doStuff</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> data</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-comment">// WHAT IS THIS IF STATEMENT???</span>
        <span class="hljs-comment">// 👇👇👇👇👇👇</span>
        <span class="hljs-keyword">if</span> (data <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">2</span>) {
            shouldAlwaysBeZero <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
        }
        <span class="hljs-comment">// 👆👆👆👆👆👆</span>

        <span class="hljs-comment">// Ignore this one for now</span>
        <span class="hljs-keyword">if</span> (hiddenValue <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">7</span>) {
            shouldAlwaysBeZero <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
        }
        hiddenValue <span class="hljs-operator">=</span> data;
    }
</code></pre><p>This seems obvious with our example function, but more often than not, you’ll have a function or system that looks like this:</p><pre data-type="codeBlock" text="function hellFunc(uint128 numberr) public view onlyOwner returns (uint256) {
        uint256 numberrr = uint256(numberr);
        Int number = Int.wrap(numberrr);
        if (Int.unwrap(number) == 1) {
            if (numbr &lt; 3) {
                return Int.unwrap((Int.wrap(2) - number) * Int.wrap(100) / (number + Int.wrap(2)));
            }
            if (Int.unwrap(number) &lt; 3) {
                return Int.unwrap((Int.wrap(numbr) - number) * Int.wrap(92) / (number + Int.wrap(3)));
            }
            if (Int.unwrap(Int.wrap(Int.unwrap(Int.wrap(Int.unwrap(Int.wrap(1)) / Int.unwrap(Int.wrap(Int.unwrap(Int.wrap(Int.unwrap(Int.wrap(numbr)))))))))) == 9) {
                return 1654;
            }
            return 5 - Int.unwrap(number);
        }
        if (Int.unwrap(number) &gt; 100) {
            _numbaar(Int.unwrap(number));
            uint256 dog = _numbaar(Int.unwrap(number) + 50);
            return (dog + numbr - (numbr / numbir) * numbor) - numbir;
        }
        if (Int.unwrap(number) &gt; 1) {
            if (Int.unwrap(number) &lt; 3) {
                return Int.unwrap((Int.wrap(2) - number) * Int.wrap(100) / (number + Int.wrap(2)));
            }
            if (numbr &lt; 3) {
                return (2 / Int.unwrap(number)) + 100 - (Int.unwrap(number) * 2);
            }
            if (Int.unwrap(number) &lt; 12) {
                if (Int.unwrap(number) &gt; 6) {
                    return Int.unwrap((Int.wrap(2) - number) * Int.wrap(100) / (number + Int.wrap(2)));
                }
            }
            if (Int.unwrap(number) &lt; 154) {
                if (Int.unwrap(number) &gt; 100) {
                    if (Int.unwrap(number) &lt; 120) {
                        return (76 / Int.unwrap(number)) + 100 - Int.unwrap(Int.wrap(uint256(uint256(uint256(uint256(uint256(uint256(uint256(uint256(uint256(uint256(uint256(uint256(numbr))))))))))))) + Int.wrap(uint256(2)));
                    }
                }
                if (Int.unwrap(number) &gt; 95) {
                    return Int.unwrap(Int.wrap((Int.unwrap(number) % 99)) / Int.wrap(1));
                }
                if (Int.unwrap(number) &gt; 88) {
                    return Int.unwrap((Int.wrap((Int.unwrap(number) % 99) + 3)) / Int.wrap(1));
                }
                if (Int.unwrap(number) &gt; 80) {
                    return (Int.unwrap(number) + 19) - (numbr * 10);
                }
                return Int.unwrap(number) + numbr - Int.unwrap(Int.wrap(nunber) / Int.wrap(1));
            }
            if (Int.unwrap(number) &lt; 7654) {
                if (Int.unwrap(number) &gt; 100000) {
                    if (Int.unwrap(number) &lt; 1200000) {
                        return (2 / Int.unwrap(number)) + 100 - (Int.unwrap(number) * 2);
                    }
                }
                if (Int.unwrap(number) &gt; 200) {
                    if (Int.unwrap(number) &lt; 300) {
                        return (2 / Int.unwrap(number)) + Int.unwrap(Int.wrap(100) / (number + Int.wrap(2)));
                    }
                }
            }
        }
        if (Int.unwrap(number) == 0) {
            if (Int.unwrap(number) &lt; 3) {
                return Int.unwrap((Int.wrap(2) - (number * Int.wrap(2))) * Int.wrap(100) / (Int.wrap(Int.unwrap(number)) + Int.wrap(2)));
            }
            if (numbr &lt; 3) {
                return (Int.unwrap(Int.wrap(2) - (number * Int.wrap(3)))) + 100 - (Int.unwrap(number) * 2);
            }
            if (numbr == 10) {
                return Int.unwrap(Int.wrap(10));
            }
            return (236 * 24) / Int.unwrap(Int.wrap(Int.unwrap(Int.wrap(Int.unwrap(Int.wrap(Int.unwrap(number)))))));
        }
        return numbr + nunber - mumber - mumber;
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hellFunc</span>(<span class="hljs-params"><span class="hljs-keyword">uint128</span> numberr</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title">onlyOwner</span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">uint256</span> numberrr <span class="hljs-operator">=</span> <span class="hljs-keyword">uint256</span>(numberr);
        Int number <span class="hljs-operator">=</span> Int.<span class="hljs-built_in">wrap</span>(numberrr);
        <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span>) {
            <span class="hljs-keyword">if</span> (numbr <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">3</span>) {
                <span class="hljs-keyword">return</span> Int.<span class="hljs-built_in">unwrap</span>((Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>) <span class="hljs-operator">-</span> number) <span class="hljs-operator">*</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">100</span>) <span class="hljs-operator">/</span> (number <span class="hljs-operator">+</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>)));
            }
            <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">3</span>) {
                <span class="hljs-keyword">return</span> Int.<span class="hljs-built_in">unwrap</span>((Int.<span class="hljs-built_in">wrap</span>(numbr) <span class="hljs-operator">-</span> number) <span class="hljs-operator">*</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">92</span>) <span class="hljs-operator">/</span> (number <span class="hljs-operator">+</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">3</span>)));
            }
            <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">1</span>)) <span class="hljs-operator">/</span> Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(numbr)))))))))) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">9</span>) {
                <span class="hljs-keyword">return</span> <span class="hljs-number">1654</span>;
            }
            <span class="hljs-keyword">return</span> <span class="hljs-number">5</span> <span class="hljs-operator">-</span> Int.<span class="hljs-built_in">unwrap</span>(number);
        }
        <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">></span> <span class="hljs-number">100</span>) {
            _numbaar(Int.<span class="hljs-built_in">unwrap</span>(number));
            <span class="hljs-keyword">uint256</span> dog <span class="hljs-operator">=</span> _numbaar(Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">+</span> <span class="hljs-number">50</span>);
            <span class="hljs-keyword">return</span> (dog <span class="hljs-operator">+</span> numbr <span class="hljs-operator">-</span> (numbr <span class="hljs-operator">/</span> numbir) <span class="hljs-operator">*</span> numbor) <span class="hljs-operator">-</span> numbir;
        }
        <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">></span> <span class="hljs-number">1</span>) {
            <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">3</span>) {
                <span class="hljs-keyword">return</span> Int.<span class="hljs-built_in">unwrap</span>((Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>) <span class="hljs-operator">-</span> number) <span class="hljs-operator">*</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">100</span>) <span class="hljs-operator">/</span> (number <span class="hljs-operator">+</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>)));
            }
            <span class="hljs-keyword">if</span> (numbr <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">3</span>) {
                <span class="hljs-keyword">return</span> (<span class="hljs-number">2</span> <span class="hljs-operator">/</span> Int.<span class="hljs-built_in">unwrap</span>(number)) <span class="hljs-operator">+</span> <span class="hljs-number">100</span> <span class="hljs-operator">-</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">*</span> <span class="hljs-number">2</span>);
            }
            <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">12</span>) {
                <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">></span> <span class="hljs-number">6</span>) {
                    <span class="hljs-keyword">return</span> Int.<span class="hljs-built_in">unwrap</span>((Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>) <span class="hljs-operator">-</span> number) <span class="hljs-operator">*</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">100</span>) <span class="hljs-operator">/</span> (number <span class="hljs-operator">+</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>)));
                }
            }
            <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">154</span>) {
                <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">></span> <span class="hljs-number">100</span>) {
                    <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">120</span>) {
                        <span class="hljs-keyword">return</span> (<span class="hljs-number">76</span> <span class="hljs-operator">/</span> Int.<span class="hljs-built_in">unwrap</span>(number)) <span class="hljs-operator">+</span> <span class="hljs-number">100</span> <span class="hljs-operator">-</span> Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-keyword">uint256</span>(numbr))))))))))))) <span class="hljs-operator">+</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-keyword">uint256</span>(<span class="hljs-number">2</span>)));
                    }
                }
                <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">></span> <span class="hljs-number">95</span>) {
                    <span class="hljs-keyword">return</span> Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>((Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">%</span> <span class="hljs-number">99</span>)) <span class="hljs-operator">/</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">1</span>));
                }
                <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">></span> <span class="hljs-number">88</span>) {
                    <span class="hljs-keyword">return</span> Int.<span class="hljs-built_in">unwrap</span>((Int.<span class="hljs-built_in">wrap</span>((Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">%</span> <span class="hljs-number">99</span>) <span class="hljs-operator">+</span> <span class="hljs-number">3</span>)) <span class="hljs-operator">/</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">1</span>));
                }
                <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">></span> <span class="hljs-number">80</span>) {
                    <span class="hljs-keyword">return</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">+</span> <span class="hljs-number">19</span>) <span class="hljs-operator">-</span> (numbr <span class="hljs-operator">*</span> <span class="hljs-number">10</span>);
                }
                <span class="hljs-keyword">return</span> Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">+</span> numbr <span class="hljs-operator">-</span> Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(nunber) <span class="hljs-operator">/</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">1</span>));
            }
            <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">7654</span>) {
                <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">></span> <span class="hljs-number">100000</span>) {
                    <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">1200000</span>) {
                        <span class="hljs-keyword">return</span> (<span class="hljs-number">2</span> <span class="hljs-operator">/</span> Int.<span class="hljs-built_in">unwrap</span>(number)) <span class="hljs-operator">+</span> <span class="hljs-number">100</span> <span class="hljs-operator">-</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">*</span> <span class="hljs-number">2</span>);
                    }
                }
                <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">></span> <span class="hljs-number">200</span>) {
                    <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">300</span>) {
                        <span class="hljs-keyword">return</span> (<span class="hljs-number">2</span> <span class="hljs-operator">/</span> Int.<span class="hljs-built_in">unwrap</span>(number)) <span class="hljs-operator">+</span> Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">100</span>) <span class="hljs-operator">/</span> (number <span class="hljs-operator">+</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>)));
                    }
                }
            }
        }
        <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">if</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">3</span>) {
                <span class="hljs-keyword">return</span> Int.<span class="hljs-built_in">unwrap</span>((Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>) <span class="hljs-operator">-</span> (number <span class="hljs-operator">*</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>))) <span class="hljs-operator">*</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">100</span>) <span class="hljs-operator">/</span> (Int.<span class="hljs-built_in">wrap</span>(Int.<span class="hljs-built_in">unwrap</span>(number)) <span class="hljs-operator">+</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>)));
            }
            <span class="hljs-keyword">if</span> (numbr <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">3</span>) {
                <span class="hljs-keyword">return</span> (Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">2</span>) <span class="hljs-operator">-</span> (number <span class="hljs-operator">*</span> Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">3</span>)))) <span class="hljs-operator">+</span> <span class="hljs-number">100</span> <span class="hljs-operator">-</span> (Int.<span class="hljs-built_in">unwrap</span>(number) <span class="hljs-operator">*</span> <span class="hljs-number">2</span>);
            }
            <span class="hljs-keyword">if</span> (numbr <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">10</span>) {
                <span class="hljs-keyword">return</span> Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(<span class="hljs-number">10</span>));
            }
            <span class="hljs-keyword">return</span> (<span class="hljs-number">236</span> <span class="hljs-operator">*</span> <span class="hljs-number">24</span>) <span class="hljs-operator">/</span> Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(Int.<span class="hljs-built_in">unwrap</span>(Int.<span class="hljs-built_in">wrap</span>(Int.<span class="hljs-built_in">unwrap</span>(number)))))));
        }
        <span class="hljs-keyword">return</span> numbr <span class="hljs-operator">+</span> nunber <span class="hljs-operator">-</span> mumber <span class="hljs-operator">-</span> mumber;
    }
</code></pre><p><em>This was one of the </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/CyfrinAudits/status/1638649541049319424"><em>Cyfrin Security Challenges</em></a>.</p><p>Here, it’s not quite so obvious if there even is an input that will cause a revert. It would be insane to write a test case for every single possible integer or scenario, so we need a programmatic way to find any outlier.</p><p>There are two popular methodologies to find these edge cases programmatically:</p><ol><li><p>Fuzz / Invariant Tests</p></li><li><p>Formal Verification / Symbolic Execution</p></li></ol><p>We will save “Formal Verification” for another video.</p><p>In Foundry, you’d write a solidity fuzz test like so:</p><pre data-type="codeBlock" text="    function testIsAlwaysZeroFuzz(uint256 randomData) public {
        // uint256 data = 0; // commented out line
        exampleContract.doStuff(randomData);
        assert(exampleContract.shouldAlwaysBeZero() == 0);
    }
"><code>    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testIsAlwaysZeroFuzz</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> randomData</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-comment">// uint256 data = 0; // commented out line</span>
        exampleContract.doStuff(randomData);
        <span class="hljs-built_in">assert</span>(exampleContract.shouldAlwaysBeZero() <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
    }
</code></pre><p>Foundry will automatically input semi-random values to <code>randomData</code> and over x number of runs, input them to the<code>doStuff</code> and check that the assertion holds.</p><p>This would be equivalent to writing many tests where <code>randomData</code> had different values, all in one test!</p><p>Now I say “semi-random” because the way your fuzzer (in our case, foundry) picks the random data isn’t truly random, and should be somewhat intelligent with the random numbers it picks. Foundry is smart enough to see the <code>if data == 2</code> conditional, and pick <code>2</code> as an input.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/533073ba6889ccb310e22e15211aeec43f5d3a228327f19e25d9400932522ad3.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/crytic/echidna">Echidna</a> — The real logo</p><p>At the moment, I think the trail of bits hybrid echidna is the best fuzzer out there due to its intelligent random number selection, but Foundry’s fuzzer (in my opinion) is easier to write code for at the moment. The echidna logo is also the best logo I’ve ever seen. Even better than the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/hievalir/status/1639110692975394816">ripped Jesus</a> logo.</p><p>Anyways, so if we run our fuzz test, it tells us exactly what input fails our test:</p><pre data-type="codeBlock" text="$ forge test -m testIsAlwaysZeroFuzz

Failing tests:
Encountered 1 failing test in test/MyContractTest.t.sol:MyContractTest
[FAIL. Reason: Assertion violated Counterexample: calldata=0x47fb53d00000000000000000000000000000000000000000000000000000000000000002, args=[2]] testIsAlwaysZeroFuzz(uint256) (runs: 6, μ: 27070, ~: 30387)
"><code>$ forge test <span class="hljs-operator">-</span>m testIsAlwaysZeroFuzz

Failing tests:
Encountered <span class="hljs-number">1</span> failing test in test<span class="hljs-operator">/</span>MyContractTest.t.sol:MyContractTest
[FAIL. Reason: Assertion violated Counterexample: <span class="hljs-keyword">calldata</span><span class="hljs-operator">=</span><span class="hljs-number">0x47fb53d00000000000000000000000000000000000000000000000000000000000000002</span>, args<span class="hljs-operator">=</span>[<span class="hljs-number">2</span>]] testIsAlwaysZeroFuzz(<span class="hljs-keyword">uint256</span>) (runs: <span class="hljs-number">6</span>, μ: <span class="hljs-number">27070</span>, <span class="hljs-operator">~</span>: <span class="hljs-number">30387</span>)
</code></pre><p>We can see that it found out if it passed <code>args=[2]</code> to the test, it was able to break our <code>assert(exampleContract.shouldAlwaysBeZero() == 0)</code>. So now, we can go back into our code, and realize we need to fix the edge case where <code>data == 2</code>, and now we are safe from the exploit of input data being 2!</p><h2 id="h-basics-of-fuzzing-summary" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Basics of Fuzzing Summary</h2><p>In summary, to write a fuzz test, we did the following</p><ol><li><p>We understood our **invariant **or “property of our system that must always hold”</p></li></ol><p>2. We wrote a test that would input random values into our function to try to break our invariant</p><h2 id="h-stateful-vs-stateless-fuzzing" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Stateful vs Stateless Fuzzing</h2><h2 id="h-stateless-fuzzing" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Stateless Fuzzing</h2><p>Now you may notice that there is another scenario where our code could have an issue, and that’s when <code>hiddenValue == 7</code>. In order for this revert to happen, you have to first set <code>hiddenValue</code> to <code>7</code>, by calling <code>doStuff</code> with the value <code>7</code> which sets <code>hiddenValue</code> to <code>7</code> and then call this function again.</p><pre data-type="codeBlock" text="uint256 hiddenValue = 0;

function doStuff(uint256 data) public {
        // Fixed this part by removing it
        // if (data == 2) {
        //     shouldAlwaysBeZero = 1;
        // }

        // Wait what&apos;s this??
        // 👇👇👇👇👇👇👇
        if (hiddenValue == 7) {
            shouldAlwaysBeZero = 1;
        }
        // 👆👆👆👆👆👆👆
        hiddenValue = data;
    }
"><code><span class="hljs-keyword">uint256</span> hiddenValue <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">doStuff</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> data</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-comment">// Fixed this part by removing it</span>
        <span class="hljs-comment">// if (data == 2) {</span>
        <span class="hljs-comment">//     shouldAlwaysBeZero = 1;</span>
        <span class="hljs-comment">// }</span>

        <span class="hljs-comment">// Wait what's this??</span>
        <span class="hljs-comment">// 👇👇👇👇👇👇👇</span>
        <span class="hljs-keyword">if</span> (hiddenValue <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">7</span>) {
            shouldAlwaysBeZero <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
        }
        <span class="hljs-comment">// 👆👆👆👆👆👆👆</span>
        hiddenValue <span class="hljs-operator">=</span> data;
    }
</code></pre><p>It takes 2 calls for our invariant to be broken.</p><ol><li><p>Call <code>doStuff</code> with <code>7</code></p></li><li><p>Call <code>doStuff</code> with any other number</p></li></ol><p>Our fuzz test written above will never be able to find this example because as it’s currently written, our test is what’s known as a “stateless fuzz test.” Which is where the state of a previous run is discarded for the next run.</p><blockquote><p>Stateless Fuzzing: Fuzzing/Fuzz Testing where the state of a previous run is discarded for the next run.</p></blockquote><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4e44ac4f85f7a8c23395f3394b195d1f2be9030b52d663b059efe4a36a4828d7.gif" 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>An example of 2 stateless fuzz runs</p><p>If we go back to the balloon example, stateless fuzzing would be similar to doing something to balloon A for one random attempt to break it, then blowing up a new balloon B and attempting to break it differently.</p><p>In the balloon example, you’d never try to break a balloon you already tried to break in the past. This seems a little silly as if our balloon invariant is that “the balloon can’t be popped” we’d want to make multiple attempts on the same balloon.</p><h2 id="h-stateful-fuzzing" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Stateful Fuzzing</h2><p>So, in software engineering, we could do “stateful fuzzing” instead. Stateful fuzzing is where the state of our previous run is the starting state of our next run.</p><blockquote><p>Stateful Fuzzing: The state of our previous fuzz run is the starting state of our next fuzz run.</p></blockquote><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/266181808f95f56e9c02a2440349251ab3f65f7360d6591b59cf8999aa82321b.gif" 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>An example of 1 stateful fuzz run, where multiple attempts are made in a run</p><p>A single stateful fuzz run would be similar to writing a test with all your assets in the same test.</p><pre data-type="codeBlock" text="function testIsAlwaysZeroUnitManyCalls() public {
        uint256 data = 7;
        exampleContract.doStuff(data);
        assert(exampleContract.shouldAlwaysBeZero() == 0);

        data = 0;
        exampleContract.doStuff(data);
        assert(exampleContract.shouldAlwaysBeZero() == 0); // this would fail
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testIsAlwaysZeroUnitManyCalls</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint256</span> data <span class="hljs-operator">=</span> <span class="hljs-number">7</span>;
        exampleContract.doStuff(data);
        <span class="hljs-built_in">assert</span>(exampleContract.shouldAlwaysBeZero() <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);

        data <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        exampleContract.doStuff(data);
        <span class="hljs-built_in">assert</span>(exampleContract.shouldAlwaysBeZero() <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>); <span class="hljs-comment">// this would fail</span>
    }
</code></pre><p><em>This is bad practice btw, don’t write your asserts in the same test, please.</em></p><p>To write a stateful fuzz test in Foundry, you’d use the <code>invariant</code> keyword, and it requires a little more setup.</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {MyContract} from &quot;../src/MyContract.sol&quot;;
import {Test} from &quot;forge-std/Test.sol&quot;;
import {StdInvariant} from &quot;forge-std/StdInvariant.sol&quot;;

contract MyContractTest is StdInvariant, Test {
    MyContract exampleContract;

    function setUp() public {
        exampleContract = new MyContract();
        targetContract(address(exampleContract));
    }

    function invariant_testAlwaysReturnsZero() public {
        assert(exampleContract.shouldAlwaysBeZero() == 0);
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-keyword">import</span> {<span class="hljs-title">MyContract</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../src/MyContract.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">Test</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"forge-std/Test.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">StdInvariant</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"forge-std/StdInvariant.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyContractTest</span> <span class="hljs-keyword">is</span> <span class="hljs-title">StdInvariant</span>, <span class="hljs-title">Test</span> </span>{
    MyContract exampleContract;

    <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>{
        exampleContract <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MyContract();
        targetContract(<span class="hljs-keyword">address</span>(exampleContract));
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">invariant_testAlwaysReturnsZero</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-built_in">assert</span>(exampleContract.shouldAlwaysBeZero() <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
    }
}
</code></pre><p>Instead of just passing random data to function calls, a stateful fuzz test (invariant) test will automatically call random functions with random data.</p><p>We use the <code>targetContract</code> function to tell Foundry that it can use any of the functions in <code>exampleContract</code>. There is just one function for this example, so it will just call <code>doStuff</code> with different values.</p><p>If we run this test, we can see the output as such, and we can see it finds out that if you call <code>doStuff</code> twice (once with the value 7), it will throw an error!</p><pre data-type="codeBlock" text="$ forge test -m invariant_testAlwaysReturnsZero

Failing tests:
Encountered 1 failing test in test/MyContractTest.t.sol:MyContractTest
[FAIL. Reason: Assertion violated]
        [Sequence]
                sender=0x000000000000000000000000000000000000018f addr=[src/MyContract.sol:MyContract]0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f calldata=doStuff(uint256), args=[7]
                sender=0x0000000008ba49893f3f5ba10c99ef3a4209b646 addr=[src/MyContract.sol:MyContract]0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f calldata=doStuff(uint256), args=[2390]
"><code>$ forge test <span class="hljs-operator">-</span>m invariant_testAlwaysReturnsZero

Failing tests:
Encountered <span class="hljs-number">1</span> failing test in test<span class="hljs-operator">/</span>MyContractTest.t.sol:MyContractTest
[FAIL. Reason: Assertion violated]
        [Sequence]
                sender<span class="hljs-operator">=</span><span class="hljs-number">0x000000000000000000000000000000000000018f</span> addr<span class="hljs-operator">=</span>[src<span class="hljs-operator">/</span>MyContract.sol:MyContract]<span class="hljs-number">0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f</span> <span class="hljs-keyword">calldata</span><span class="hljs-operator">=</span>doStuff(<span class="hljs-keyword">uint256</span>), args<span class="hljs-operator">=</span>[<span class="hljs-number">7</span>]
                sender<span class="hljs-operator">=</span><span class="hljs-number">0x0000000008ba49893f3f5ba10c99ef3a4209b646</span> addr<span class="hljs-operator">=</span>[src<span class="hljs-operator">/</span>MyContract.sol:MyContract]<span class="hljs-number">0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f</span> <span class="hljs-keyword">calldata</span><span class="hljs-operator">=</span>doStuff(<span class="hljs-keyword">uint256</span>), args<span class="hljs-operator">=</span>[<span class="hljs-number">2390</span>]
</code></pre><h2 id="h-wait-whats-an-invariant-again" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Wait, what’s an invariant again?</h2><p>Now, important aside on how Foundry uses the term <strong>invariant</strong>. As we’ve described, an invariant is a property of the system that must always hold, but Foundry uses the term to mean “stateful fuzzing.” Just keep this in mind.</p><ul><li><p>Foundry Invariant Tests == Stateful Fuzzing</p></li><li><p>Foundry Fuzz Tests == Stateless Fuzzing</p></li><li><p>Invariants == Property of the system that must always hold</p></li></ul><p>So in an actual smart contract, your invariant won’t be that a balloon shouldn’t pop or some function should always be zero; it’ll be something like:</p><ul><li><p>New tokens minted &lt; inflation rate</p></li><li><p>There should only be 1 winner of a random lottery</p></li><li><p>Someone shouldn’t be able to take more money out of the protocol than they put in</p></li></ul><p>And let me tell you what, at this point, you now know all the basics of Fuzzing! Congratulations! Maybe now you take a break and try writing some tests yourself, and then come back to the video.</p><h2 id="h-this-is-the-new-bare-minimum" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">This is the new bare minimum</h2><p>This is the new floor for security in web3. It’s systematic to do, anyone can learn how to do it, and it can save a LOT of headaches.</p><ol><li><p>Understand your invariants</p></li><li><p>Write stateful fuzz tests for them</p></li><li><p>Don’t go to an audit before.</p></li><li><p>If you do, make sure your auditors help you understand your invariants!</p></li></ol><p>Now you understand the basics of fuzzing &amp; invariant tests, you can go use the tools you like! To learn more about advanced stateful fuzz testing, be sure to stay tuned, we have an advanced video coming up soon! Additionally, read the Foundry documentation on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://book.getfoundry.sh/forge/invariant-testing#handler-based-testing">Handler method</a>, as that’s the recommended way to build the most sophisticated stateful fuzz tests.</p><p>This article from <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/horsefacts.eth/Jex2YVaO65dda6zEyfM_-DXlXhOWCAoSpOx5PLocYgw">Horsefacts</a> also does an amazing walkthrough.</p><p>Have Fun!</p><p>😸😸Follow Patrick!😸😸</p><p>Book a smart contract audit: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/">Cyfrin</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/@PatrickAlphaC/videos">https://www.youtube.com/@PatrickAlphaC/videos</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/patrickalphac">https://twitter.com/patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/@patrickalphac">https://medium.com/@patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.tiktok.com/@patrickalphac">https://www.tiktok.com/@patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/channel/UCMHHNgcezTnfrJUM1vIiZlQ">https://www.youtube.com/channel/UCMHHNgcezTnfrJUM1vIiZlQ</a></p>]]></content:encoded>
            <author>patrickalphac-old@newsletter.paragraph.com (Patrick Collins)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/ecdcd745b9ad0f45e79a2e83739266a7353a94ad98a90cfe3760af19533e8b56.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Smart Contract Audit | What it is, and what to expect]]></title>
            <link>https://paragraph.com/@patrickalphac-old/smart-contract-audit-what-it-is-and-what-to-expect</link>
            <guid>Ptpd5Sh7M0uMN3ipMfcL</guid>
            <pubDate>Fri, 07 Apr 2023 14:06:15 GMT</pubDate>
            <description><![CDATA[A smart contract audit is a time-boxed security-based code review on your smart contract/web3 system. An auditor’s goal is to find as many vulnerabilities as possible and educate the client on ways to improve the security of their codebase moving forward.What is a Smart Contract Audit?A smart contract audit is a time-boxed security-based code review on your smart contract/web3 system. An auditor’s goal is to find as many vulnerabilities as possible and educate the client on ways to improve th...]]></description>
            <content:encoded><![CDATA[<h2 id="h-a-smart-contract-audit-is-a-time-boxed-security-based-code-review-on-your-smart-contractweb3-system-an-auditors-goal-is-to-find-as-many-vulnerabilities-as-possible-and-educate-the-client-on-ways-to-improve-the-security-of-their-codebase-moving-forward" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">A <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/">smart contract audit</a> is a time-boxed security-based code review on your smart contract/web3 system. An auditor’s goal is to find as many vulnerabilities as possible and educate the client on ways to improve the security of their codebase moving forward.</h2><h2 id="h-what-is-a-smart-contract-audit" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What is a Smart Contract Audit?</h2><blockquote><p>A <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/">smart contract audit</a> is a time-boxed security-based code review on your smart contract/web3 system. An auditor’s goal is to find as many vulnerabilities as possible and educate the client on ways to improve the security of their codebase moving forward.</p></blockquote><p>Auditors use a combination of manual and automated tools to find these vulnerabilities.</p><h2 id="h-why-are-smart-contract-audits-so-important" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why are smart contract audits so important?</h2><p>According to a research study by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.chainalysis.com/reports/2022-biggest-year-ever-for-crypto-hacking/">Chainalysis</a>, 2022 was the year the most value was stolen from smart contracts.</p><p>Due to the immutability of the blockchain, once a smart contract is deployed, you can’t change it, so you’d better get it right. The blockchain is an adversarial environment, and your protocol needs to be prepared for malicious users.</p><p>But even more than just saving your protocol from hacks, an audit can improve your developer’s understanding of code, improving their speed and effectiveness of features moving forward.</p><p>Additionally, there is an <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rekt.news/">entire website</a> dedicated to how many hacks happen, and we need to do our best to prevent that list from growing as a community.</p><h2 id="h-smart-contract-audit-benefits" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Smart Contract Audit Benefits</h2><ul><li><p>Find vulnerabilities</p></li><li><p>Level-up developers</p></li><li><p>Teach best practices and the most modern tooling</p></li></ul><p>Often, one audit isn’t enough. Many protocols go on a security journey that includes multiple audits and services like:</p><ul><li><p>Formal Verification</p></li><li><p>Competitive Audits</p></li><li><p>Bug Bounty Programs</p></li></ul><p>We’ll break these down in a future post.</p><h2 id="h-smart-contract-auditors" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Smart Contract Auditors</h2><p>There are a lot of companies that offer smart contract auditing services, like</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trailofbits.com/">Trail of Bits</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://consensys.net/diligence/">Consensys Diligence</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.openzeppelin.com/">Openzeppelin</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://sigmaprime.io/">Sigma Prime</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://spearbit.com/">SpearbitDAO</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mixbytes.io/">MixBytes</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.watchpug.org/">WatchPug</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trustindistrust.com/">Trust</a></p></li><li><p>And, of course, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/">Cyfrin</a>!</p></li></ul><p>You can see a more detailed list of the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://patrickalphac.medium.com/top-7-smart-contract-auditors-bec7bd70dd9f">top 7 smart contract auditors here</a>.</p><p>Additionally, there are a lot of independent auditors that do great work as well.</p><h2 id="h-smart-contract-audit-process" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Smart Contract Audit Process</h2><p>A typical audit looks like this:</p><h2 id="h-1-price-and-timeline" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">1. Price &amp; Timeline</h2><p>A protocol can reach out before or after their code is finished. Ideally, they reach out some time before so the auditor can have enough time to schedule them.</p><p>Once they reach out, the teams will discuss how long the audit will take based on the scope and code complexity.</p><p>How long the audit will take depends on how many lines of code.<br>A very rough approximation of how long an audit takes depending on how many source lines of code you have can be found here:</p><p>The duration sets the price, and prices can range widely based on the different auditors at the time of writing. At the time of recording, a one-week-long audit can go anywhere from</p><p>Duration: Price</p><pre data-type="codeBlock" text="- 1 week: $5,000 - $100,000
"><code>- 1 week: <span class="hljs-variable">$5</span>,000 - <span class="hljs-variable">$100</span>,000
</code></pre><p>The range is massive, but I have seen pricing anywhere in this range.</p><h2 id="h-2-commit-hash-down-payment-start-date" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2. Commit Hash, Down payment, Start Date</h2><p>Auditors need to know exactly what code they are auditing and use the commit hash of your repo to do so.<br>Once you have a commit hash, you can reach a start date and finalize the price.</p><h2 id="h-3-audit-begins" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">3. Audit Begins</h2><p>Then the audit starts! Your auditors will use every tool in their arsenal to find vulnerabilities in your code.</p><h2 id="h-4-initial-report" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">4. Initial Report</h2><p>After the period ends, the auditors will give you an initial report that looks <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ChainAccelOrg/cyfrin-audit-reports/blob/main/reports/2023-03-13-beanstalk_wells_v0.1.pdf">like this</a>.</p><p>All their findings are listed by severity, usually in formatted into:</p><ul><li><p>High</p></li><li><p>Medium</p></li><li><p>Low</p></li><li><p>Informational / Non-critical / Gas</p></li></ul><p>High, medium, and low represent the severity of the impact and likelihood of each vulnerability.<br>Informational, Gas, and Non-Critical are findings to improve the efficiency of your code, code structure, and best practice improvement suggestions are not vulnerabilities but ways to improve your code.</p><h2 id="h-5-mitigation-begins" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">5. Mitigation Begins</h2><p>The protocol’s team will then have an agreed-upon time to fix the vulnerabilities found in the initial audit report. Sometimes, depending on the severity of the findings, this may be long but is often much shorter than the audit itself.</p><h2 id="h-6-final-report" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">6. Final Report</h2><p>After the protocol makes the changes, the audit team will do a final audit report exclusively on the fixes made to address the issues brought up in the initial report.</p><p>And then, hopefully, the auditors and protocols have had a great experience and will work together to stay secure in the future!</p><h2 id="h-how-to-get-the-most-out-of-a-smart-contract-audit" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How to get the most out of a smart contract audit</h2><p>To get the most out of an audit, you should:</p><p>Have clear documentation</p><ol><li><p>Robust test suite</p></li><li><p>Ideally, including fuzz tests</p></li><li><p>Code should be commented &amp; readable</p></li><li><p>Modern best practices followed</p></li><li><p>Communication channel between developer and auditors</p></li><li><p>Do an initial video walkthrough of the code</p></li></ol><p>However, the most important part of the process is during the audit.</p><p>You want to think of you and your auditor as a team to get the best results out of your audit. One of the best ways to do this is to have a dedicated channel where auditors can ask questions to the developers.</p><p>Additionally, the more context, documentation, and information they can read, the better. Be sure it’s easy for anyone to walk through your code and understand what it’s supposed to do.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ZhangZhuoSJTU/Web3Bugs">80% of all bugs</a> are due to business logic issues, so the auditors need to understand what the protocol should do more than they should understand the actual code!</p><p>Breakdown of bugs between <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ZhangZhuoSJTU/Web3Bugs/blob/main/papers/icse23.pdf">machine auditable and unauditable</a></p><p>Having a modern test suite &amp; tooling can also make it so auditors spend less time fidgeting with your tooling and more time finding issues.</p><p>A high-level video walkthrough of your code should be the first thing you and the auditors do together.</p><h2 id="h-after-the-audit" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">After the Audit</h2><div data-type="youtube" videoId="fT2EMEIM1DA">
      <div class="youtube-player" data-id="fT2EMEIM1DA" style="background-image: url('https://i.ytimg.com/vi/fT2EMEIM1DA/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=fT2EMEIM1DA">
          <img src="{{DOMAIN}}/editor/youtube/play.png" class="play"/>
        </a>
      </div></div><p>We highly encourage you to act on the recommendations of an audit report, we’ve seen too many protocols not take warnings seriously, and that be the attack vector that gets exploited.</p><p>Additionally, if you change your codebase, that is now unaudited code, and should not be pushed, no matter how small the change may be. If you change your code, consider getting that piece of code audited.</p><p>And often, depending on how much money your protocol will secure, you should consider getting another audit anyway!</p><h2 id="h-what-an-audit-isnt" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What an audit isn’t</h2><p>One audit does not mean your code is bug-free.</p><p>Now here is the thing, an audit does not mean your code is bug-free. It’s a security journey where your team should level up on security.</p><p>No matter how experienced an auditor or audit firm is, people at all levels of experience will miss something. On the sad day that happens, get together on an emergency communication channel with your auditors and figure out to remedy the situation quickly.</p><p>Insurance is often a good idea for even the most audited protocols.</p><p>So with that, now you have a good idea of the smart contract audit process end to end and what to expect. A smart contract audit is more of a security journey between the protocol and the auditors, and having a security-focused mindset doesn’t end even after the audit.</p><p>If you’re looking for an audit, be sure to contact the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/">Cyfrin team</a>.</p><p>And as always, stay safe out there!</p><h2 id="h-follow-patrick" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">😸😸Follow Patrick!😸😸</h2><p>Book a smart contract audit: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/">Cyfrin</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/@PatrickAlphaC/videos">YouTube</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/patrickalphac">Twitter</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/@patrickalphac">Medium</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.tiktok.com/@patrickalphac">TikTok</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/channel/UCMHHNgcezTnfrJUM1vIiZlQ">Twitch Stream Uploads &amp; Shorts</a></p><blockquote><p>*New to trading? Try <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/coinmonks/crypto-trading-bot-c2ffce8acb2a"><em>crypto trading bots</em></a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/coinmonks/top-10-crypto-copy-trading-platforms-for-beginners-d0c37c7d698c"><em>copy trading</em></a> on *<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/coinmonks/crypto-exchange-dd2f9d6f3769"><em>best crypto exchanges</em></a></p></blockquote><blockquote><p>Join Coinmonks<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/coincodecap"> Telegram Channel</a> and<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/c/coinmonks/videos"> Youtube Channel</a> get daily <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://coincodecap.com/">Crypto News</a></p></blockquote><h2 id="h-also-read" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Also, Read</h2><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/coinmonks/free-crypto-signals-48b25e61a8da">Free Crypto Signals</a> | <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/coinmonks/crypto-trading-bot-c2ffce8acb2a">Crypto Trading Bots</a></p></li><li><p>An ultimate guide to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/coinmonks/leveraged-token-3f5257808b22">Leveraged Token</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/coinmonks/top-17-folding-electric-bikes-5e296f0918cb">16 Best Folding Electric Bikes</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/coinmonks/the-28-best-electric-bikes-review-and-buying-guide-in-2023-7bb3146cb403">28 Best Electric Bikes Review</a></p></li><li><p>Top 3 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/coinmonks/top-3-binance-futures-trading-bots-e6031f84b3f9">Binance Futures Trading Bots</a></p></li></ul>]]></content:encoded>
            <author>patrickalphac-old@newsletter.paragraph.com (Patrick Collins)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/31fbc95aff8df2b7a8d635e5327560c4f938d4aa54d2c5a4200eb5802d7770aa.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Top 7 Smart Contract Auditors - Patrick Collins - Medium]]></title>
            <link>https://paragraph.com/@patrickalphac-old/top-7-smart-contract-auditors-patrick-collins-medium</link>
            <guid>4kzeQVAQOJmhL1rhxcUU</guid>
            <pubDate>Fri, 07 Apr 2023 03:16:04 GMT</pubDate>
            <description><![CDATA[We look across the industry at the top smart contract auditors in Web3. Smart contract audits are the lifeblood of the Web3 security space and are crucial to ensuring we stay safe.I am a co-founder and security researcher from Cyfrin, where we do smart contract audits. This is my opinionated take on top smart contract audit firms along with Cyfrin. The only way Web3 scales is if we increase our security, so I want to ensure that other top firms get the exposure they deserve. Auditors left off...]]></description>
            <content:encoded><![CDATA[<h2 id="h-we-look-across-the-industry-at-the-top-smart-contract-auditors-in-web3-smart-contract-audits-are-the-lifeblood-of-the-web3-security-space-and-are-crucial-to-ensuring-we-stay-safe" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">We look across the industry at the top smart contract auditors in Web3. Smart contract audits are the lifeblood of the Web3 security space and are crucial to ensuring we stay safe.</h2><p><em>I am a co-founder and security researcher from </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/"><em>Cyfrin</em></a>, where we do smart contract audits. <em>This is my opinionated take on top smart contract audit firms along with Cyfrin. The only way Web3 scales is if we increase our security, so I want to ensure that other top firms get the exposure they deserve. Auditors left off this list are not necessarily poor choices, I may have just missed them.</em></p><h2 id="h-what-is-a-smart-contract-audit" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What is a Smart Contract Audit</h2><p>A <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/blog/what-is-a-smart-contract-audit">smart contract audit</a> is a time-boxed security-based code review on your smart contract / Web3 system. An auditor’s goal is to find as many vulnerabilities as possible and educate the client on ways to improve the security of their codebase moving forward.</p><p>Auditors use a combination of manual and automated tools to find these vulnerabilities.</p><p>However, a smart contract audit does not guarantee your code is bug-free. At the end of the day, your protocol&apos;s security is yours and your auditor&apos;s responsibility, and sometimes multiple audits or another security tooling might be needed.</p><p>A professional audit group can and will give you all the guidance you need to move forward on your security journey so you can feel confident deploying.</p><h2 id="h-why-we-need-smart-contract-audits" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why We Need Smart Contract Audits</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a9c1b4043154bc90b9c6421a74a77529914d7aac37a76f868302eb58ac6983ce.webp" 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>Image from <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.chainalysis.com/reports/2022-biggest-year-ever-for-crypto-hacking/">Chainalysis</a></p><p>The image above represents the total dollar amount stolen from DeFi for the entire year of 2022, 80% of that value was exclusively in DeFi. According to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://defillama.com/">DeFillama</a>, the current locked value of all DeFi is 50 billion dollars.</p><p><strong>This means that over 6% of all DeFi value has been subject to a hack!</strong></p><p>If we want blockchain and DeFi to come to the masses, they cannot be worried that there is a 6% chance they will wake up to find their funds exploited. <strong>We have to do better than this.</strong></p><p>This is why audits are so important:</p><ul><li><p>Keep your protocol safe</p></li><li><p>Help Web3 gain authority</p></li><li><p>Educate your team on best practices</p></li></ul><p>That last bullet is what I call the **hidden benefit of smart contract audits. **Getting an audit and working with a group of security and smart contract experts can improve your team&apos;s skill in developing protocols. They should give you feedback on vulnerabilities <strong>and</strong> educate your team on improving. They are security and developer experts, after all!</p><h2 id="h-how-to-choose-a-smart-contract-auditor" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How to Choose a Smart Contract Auditor</h2><ol><li><p>Understand the auditor skill set</p></li><li><p>Understand your price point</p></li><li><p>Understand their methodology</p></li></ol><h2 id="h-understand-the-auditor-skill-set" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Understand the auditor skill set</h2><p>You want to ensure the auditor has done work in the domain you’re looking for an audit on. If you want an audit on Solana and you work with an EVM specialist group, you’re going to have a bad time.</p><p>Maybe you want a DeFi audit, and you’re working with a firm that only understands NFTs; this is also a recipe for disaster.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2563dc7e3dd0aa92347e534e39880518a51e5c7e4f98c799bfbe49afa7cc3634.gif" 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>You having a bad time if you don’t know their skill set</p><p>An easy way to see what kinds of projects an auditor can do is to look at a list of their previous audits. Most auditors will have some publicly displayed audits as a showcase of work, and you can decide based on their past if they are right for you.</p><h2 id="h-understand-your-price-point" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Understand your price point</h2><p>Large firms will often cost more than smaller firms and independent auditors. Typically, you can find “cheaper” audits with smaller companies and independent auditors, but the quality can vary.</p><p>I’ve seen a **ton **of fantastic solo auditors, though, so don’t discount a solo auditor who wants to audit your protocol.</p><p>Pricing varies wildly depending on the auditors, so understand the next point to get the best idea for a price point.</p><h2 id="h-understand-their-methodology" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Understand their methodology</h2><p>Security researcher <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/tinchoabbate/status/1640737272130674690">Tincho</a> walks through his audit methodology</p><p>Before locking down any payment, you need to verify the following:</p><ul><li><p>Exactly which auditor(s) will conduct the audit</p></li><li><p>What tools will they use (fuzzing, formal verification, etc)</p></li><li><p>If they want a communication channel between your developers and the auditors</p></li></ul><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ZhangZhuoSJTU/Web3Bugs">80% of hacks</a> are not machine auditable and often come from poor implementation of business logic. Because of this, auditors need as much context as possible in the form of:</p><ul><li><p>Documentation</p></li><li><p>Q&amp;A Channel with Developers</p></li><li><p>Code Natspec</p></li></ul><p>If an auditor doesn’t tell you who is doing the audit, what tools they are using, or doesn’t want to have a direct line of communication between your protocol devs and the auditors, there is a good chance they are going to do shoddy work.</p><p>Additionally, I think auditors should try to improve your test suite with <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/@patrickalphac/fuzz-invariant-tests-the-new-bare-minimum-for-smart-contract-security-87ebe150e88c">fuzzing/property/invariant tests</a>, but it’s not required.</p><h2 id="h-how-to-prepare-for-a-smart-contract-audit" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How to Prepare for a Smart Contract Audit</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d205e3a9a79abc94a960f027ed6c3873df09c6ec64ad99149d377fbbdb73a615.webp" 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>How to prepare for a smart contract audit</p><p>Imagine two random developers drop 5,000 lines of code you’ve never seen on your desk and tell you that the code needs to be cleaned up and spotless in two weeks.</p><blockquote><p>Developer A tells you what the code should do, it has a test suite, and they say, “feel free to ask me any questions you may have!”</p><p>Developer B says, “Don’t talk to me till it’s done.”</p></blockquote><p>Your review of developer A’s code will be 100 times better than developer B. Be like developer A.</p><p>To get the most out of an audit, you should:</p><ol><li><p>Have clear documentation</p></li><li><p>Robust test suite (Ideally, including <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/@patrickalphac/fuzz-invariant-tests-the-new-bare-minimum-for-smart-contract-security-87ebe150e88c">fuzz tests</a>)</p></li><li><p>Code should be commented &amp; readable</p></li><li><p>Modern best practices followed</p></li><li><p>A communication channel between developers and auditors</p></li><li><p>You are prepared to do an initial video walkthrough of your code</p></li></ol><p>You want to think of you and your auditor as a team to get the best results out of your audit. One of the best ways to do this is to have a dedicated channel where auditors can ask questions to the developers.</p><p>Additionally, the more context, documentation, and information they can read, the better. Be sure it’s easy for anyone to walk through your code and understand what it’s supposed to do. 80% of all bugs are due to business logic issues, so the auditors need to understand what the protocol should do more than they should understand the actual code!</p><p>You can learn more about the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/blog/what-is-a-smart-contract-audit">smart contract auditing process here</a>.</p><h2 id="h-top-smart-contract-auditors" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Top Smart Contract Auditors</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c0d2e2c69c98fd7d665d1f93e8e53f8ee144f2dfaad2c9f61286db75a4d2ffac.webp" 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>Finally!</p><p>I wanted to make sure you had all this context before giving you this list because I’ve seen protocols that want an audit for one of two reasons:</p><ol><li><p>Marketing</p></li><li><p>Security &amp; Marketing</p></li></ol><p>Be like #2. Getting “an” audit and treating all audits the same can be tempting but should **not **be done. You want to treat an audit like you, and your auditor are teaming up to secure your code.</p><p>Here it is, my list of top 7 auditors in no particular order, and why I think they are a top auditor.</p><h2 id="h-cyfrin" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Cyfrin</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7159630086329bf715061c96596e29738bdda655ce0df771b6dc585ec4845eae.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/#hero">https://www.cyfrin.io/#hero</a></p><p><em>Please keep in mind I am the co-founder of </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/#hero"><em>Cyfrin</em></a>.</p><p>As someone who wants to see the success of Web3, I was furious with the state of security in Web3. $3.8B lost in 2022 is a horrifying statistic, so I felt compelled to jump in and help secure DeFi and blockchain.</p><p>The Cyfrin team has some of the top engineers and auditors in the space, like:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/hansfriese">Hans</a> | #1 Ranked Auditor as of Writing on Code4rena</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/alexroan">Alex</a> | Ex-Chainlink Labs Engineer in charge of $5B+ DeFi integrations</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/0kage_eth">0Kage</a> | Code4rena Top Finisher and Experienced FinTech Engineer</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/carlitox477">Carlos</a> | Code4rena Top Finisher &amp; Expert Solidity Engineer</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/giovannidisiena">Gio</a> | Expert Solidity Engineer</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/PatrickAlphaC">Patrick</a> | <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=M576WGiDBdQ">Most Watched Solidity Education Video(s) of All Time</a></p></li></ul><p>We thrive on finding as many bugs as possible and finding ways to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/BeanstalkFarms/Wells/pull/62">improve your codebase</a> and test suite.</p><p>Web3 security needs a new narrative, and we are excited to push the security space forward. We are a smaller group at the time of writing as we only launched 2 months ago!</p><p>You can find a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ChainAccelOrg/cyfrin-audit-reports">list of notable audits (and skillsets) for Cyfrin here</a>, including the Beanstalk Wells integration and LinkPool.</p><h2 id="h-trail-of-bits" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Trail Of Bits</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8ab6b4aecbe38bb8fad0e3bb50ef5271ef10c68c6214d8eca2dc8862114bf942.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trailofbits.com/">https://www.trailofbits.com/</a></p><p>I *always *tell people to check out <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trailofbits.com/">Trail of Bits</a>. They are one of the firms in Web3 security consistently pushing the bar in a practical sense. They don’t just give an audit, they give you all the tools you need to be successful in smart contract security as well.</p><p>The Trail of Bits team builds some of the most popular and widely used tools like:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/crytic/slither">Slither</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/trailofbits/manticore">Manticore</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/crytic/echidna">Echidna</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/crytic/properties">Properties</a></p></li></ul><p>And so many more. They are dedicated to educating the Web3 space as well with tons of free educational content and blogs.</p><p>Interview I did with Head of Blockchain Engineering <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Montyly">Josselin</a></p><div data-type="youtube" videoId="3pWYvtx_sjA">
      <div class="youtube-player" data-id="3pWYvtx_sjA" style="background-image: url('https://i.ytimg.com/vi/3pWYvtx_sjA/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=3pWYvtx_sjA">
          <img src="{{DOMAIN}}/editor/youtube/play.png" class="play"/>
        </a>
      </div></div><p>Trail of Bits is a large group consistently rated one of the top firms in Web3 for good reason, and I’d definitely classify myself as a fanboy.</p><p>You can find a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/trailofbits/publications/tree/master/reviews">list of notable audits (and skillsets) for Trail Of Bits here</a>, like Uniswap, Yearn, and Compound.</p><h2 id="h-openzeppelin" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">OpenZeppelin</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/16f906bb7b2ab92512fe6679f24abeb57b3f4ab1a6fed2ca8c8b1ca507aafdc9.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.openzeppelin.com/">https://www.openzeppelin.com/</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.openzeppelin.com/">OpenZeppelin</a> is another group that constantly pushes the envelope by raising the state of Web3, which is why I’m a massive fan of their work. The <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.openzeppelin.com/contracts">OpenZeppelin Contracts</a> is the standard library for solidity that 95% of the rest of Web3 uses and trusts to build their smart contracts.</p><p>You should hold onto every report you read from the OpenZeppelin team like gold, as the information they give is some of the best in the business, and their team is constantly raising the bar for security.</p><p>OpenZeppelin is a large group used by some of the top protocols in the space, like Aave, Optimism, and Compound.</p><p>I really can’t speak highly enough about the skills of this team.</p><p>You can find a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.openzeppelin.com/security-audits/">list of notable audits (and skillsets) for OpenZeppelin here.</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/07e79ac0cbf1e1922b42e98936df0177e75647461889c356660e4c2282f6ff2f.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://consensys.net/diligence/">https://consensys.net/diligence/</a></p><p>Part of the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://consensys.net/">Consensys</a> team, one of the most well-known groups in Web3 behind projects like Metamask, Infura, and Truffle, their security team is also first-class. They are a large group with a great track record.</p><p>The Diligence team is another team that values powerful fuzzing and recently came out with a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ConsenSys/diligence-fuzzing">fuzzer-as-a-service</a> product. To me, this signals that they not only understand security, but they understand trying to scale security throughout all of Web3. You can tell when a group cares when they make tooling &amp; educational material that makes your life better instead of hoarding it all for themselves.</p><p>They additionally have <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://consensys.net/diligence/scribble/">formal verification</a> tooling (similar to Trail of Bits) if you want to go the extra mile.</p><p>You can see a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://consensys.net/diligence/audits/">list of Consensys Diligence audits here</a>, including Aragon, RocketPool, and Fei.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/985627ba8f8561e5d5161d13e2299ad55613e0ff011250849f03f207caf81e11.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://spearbit.com/">https://spearbit.com/</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://spearbit.com/">Spearbit</a> is a decentralized network of security experts that shakes the game up.</p><p>Unlike traditional auditing firms, which employ teams of full-time security researchers, Spearbit sources top talent from everywhere in the Web3 ecosystem to assemble the best possible team.</p><p>Now you might be thinking, “wait, wouldn’t the quality vary if they have different auditors on different projects?”- however, this hasn’t stopped them from consistently being one of the best in the business.</p><p>SpearbitDAO proves the decentralization ethos works, as many top auditors and researchers go solo — so periodically combining them into one group makes them all the better!</p><p>You can see a list of <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/spearbit/portfolio/tree/master/pdfs">SpearbitDAO audits here</a>, including SudoSwap, LooksRare, and ArtGobblers.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/670fc19b73c8c83bd91e2fbcfe687a7b2eb9307031a58d5e96dcde97709b3325.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dedaub.com/">https://dedaub.com/</a></p><p>A lesser-known group, I’ve only seen the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dedaub.com/">Dedaub</a> team ship amazing reports, and it was a little confusing to me why so few people know about them.</p><p>They are another team that ships more than <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://library.dedaub.com/">just security audits</a>, with coding libraries and helpful alpha on social media.</p><p>As an ex-Chainlink engineer myself (ex-DevRel technically), I’ve witnessed the good this team can do on an audit.</p><p>You can see a list of projects<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dedaub.com/"> they’ve worked with</a>, including Chainlink, Liquity, and Blur.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/154eb4af2182e97bf5a31a65800ad30b74e1559afdda39930351fb7d26a7591d.webp" 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><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trustindistrust.com/">https://www.trustindistrust.com/</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trustindistrust.com/">Trust</a> is a solo auditor consistently at the top of the competitive audit leaderboards and has done fantastic work educating all of Web3. I especially wanted to highlight him to say you don’t always need to go with a firm! Solo auditors can often be cheaper, with as much skill or more than a massive firm.</p><p>He has <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://smartcontractshacking.com/?referral=trust">an auditor course</a>, consistently gives <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trustindistrust.com/blog">beautiful write-ups</a>, and has made a massive impact in keeping Web3 safe by himself!</p><p>I had the pleasure of interviewing him, and he gave me all the tips and tricks one would need to move forward and be a successful security engineer in Web3.</p><div data-type="youtube" videoId="VRK2rLFPU0o">
      <div class="youtube-player" data-id="VRK2rLFPU0o" style="background-image: url('https://i.ytimg.com/vi/VRK2rLFPU0o/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=VRK2rLFPU0o">
          <img src="{{DOMAIN}}/editor/youtube/play.png" class="play"/>
        </a>
      </div></div><p>Interview with Trust (Or)</p><p>You can see a list of <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.trustindistrust.com/trust-security-audits">Trust audits here, </a>including The Graph and Vagabond.</p><h2 id="h-more" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">More</h2><p>I wanted to keep the list short because the algorithm likes it like that, but here are some more firms and solo auditors that do a fantastic job. If you think I’m missing any, let me know, and I’ll do an assessment.</p><h2 id="h-firms" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Firms</h2><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://sigmaprime.io/">Sigma Prime</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mixbytes.io/">MixBytes</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.watchpug.org/">WatchPug</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.halborn.com/">Halborn</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://code4rena.com/">Code4rena</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.sherlock.xyz/">Sherlock</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://runtimeverification.com/">Runtime Verification</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.certora.com/">Certora</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://paladinsec.co/services/">Paladin</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dedaub.com/">Dedaub</a></p></li></ul><h2 id="h-solo" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solo</h2><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/pashovkrum">Pashov</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/IAm0x52">0x52</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/zachobront">obront.eth</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/romanboehr">Romanboehr</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/cccz">cccz</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/akshaysrivastv">Akshay Srivastav</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/0xKaden">Kaden.eth</a></p></li></ul><h2 id="h-follow-patrick" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🐸🐸Follow Patrick!🐸🐸</h2><p>Book a smart contract audit: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/">Cyfrin</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/@PatrickAlphaC/videos">https://www.youtube.com/@PatrickAlphaC/videos</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/patrickalphac">https://twitter.com/patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/@patrickalphac">https://medium.com/@patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.tiktok.com/@patrickalphac">https://www.tiktok.com/@patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.linkedin.com/in/patrickalphac/">https://www.linkedin.com/in/patrickalphac/</a></p>]]></content:encoded>
            <author>patrickalphac-old@newsletter.paragraph.com (Patrick Collins)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/09371393a52e9eeee3deb9e9e4f1f8a4f9b98f741bcfcd20cfcfb65451c8fdb0.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[“Damn Vulnerable DeFi” Creator Teaches You How To Audit]]></title>
            <link>https://paragraph.com/@patrickalphac-old/damn-vulnerable-defi-creator-teaches-you-how-to-audit</link>
            <guid>sEF7Y1BCcFFejUNxISVm</guid>
            <pubDate>Mon, 20 Mar 2023 01:29:36 GMT</pubDate>
            <description><![CDATA[We meet up with Tincho, Damn Vulnerable DeFi creator and previous Openzeppelin lead auditor, on what his exact audit process looks like end-to-end. We do a mock audit of ENS to show you how to do it.We had the pleasure of interviewing Tincho on his **exact **audit process he uses to make web3 more secure. You can watch the summary video here: Additionally, if you’d like to watch the full interview, you can find that on my YouTube as well. Tincho broke down his process for us to get some conte...]]></description>
            <content:encoded><![CDATA[<h2 id="h-we-meet-up-with-tincho-damn-vulnerable-defi-creator-and-previous-openzeppelin-lead-auditor-on-what-his-exact-audit-process-looks-like-end-to-end-we-do-a-mock-audit-of-ens-to-show-you-how-to-do-it" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">We meet up with Tincho, Damn Vulnerable DeFi creator and previous Openzeppelin lead auditor, on what his exact audit process looks like end-to-end. We do a mock audit of ENS to show you how to do it.</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f0bcd59b4c244213f6b97f3d7bc782b8412eb022e7d7d3c90d58316a102e649b.webp" 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>We had the pleasure of interviewing <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/tinchoabbate">Tincho</a> on his **exact **audit process he uses to make web3 more secure.</p><p>You can watch the summary video here:</p><div data-type="youtube" videoId="A-T9F0anN1E">
      <div class="youtube-player" data-id="A-T9F0anN1E" style="background-image: url('https://i.ytimg.com/vi/A-T9F0anN1E/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=A-T9F0anN1E">
          <img src="{{DOMAIN}}/editor/youtube/play.png" class="play"/>
        </a>
      </div></div><p>Additionally, if you’d like to watch the full interview, you can find that on my <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=bYdiF06SLWc">YouTube as well</a>.</p><p>Tincho broke down his process for us to get some context. However, one thing he was adamant about was the following:</p><blockquote><p>There is no silver bullet for auditing.</p></blockquote><p>This was something that was repeated throughout our interview. Every auditor is going to learn to approach problems differently, and his methodology might not be the same as one you might invoke. Find what works for you, and go to town!</p><p>But here is the summary of how Tincho approaches his audits. We did a mock audit of the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ensdomains/ens">ENS</a> protocol to showcase precisely the steps Tincho takes to do an audit.</p><h2 id="h-1-get-context" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">1. Get Context</h2><p>Read the documentation.</p><p>Read. The. Docs.</p><p>Before he even starts looking at code, he makes sure to get an understanding of what the protocol is supposed to do. 80% of all bugs and exploits come from business logic exploits, so if you don’t understand the business logic of the code, it will be impossible to find exploits!</p><p>He may also read reports on previous audits, get familiar with similar protocols, etc. Anything to prime himself for the security journey he is about to take.</p><h2 id="h-2-bring-your-tools" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2. Bring your tools</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2f3ae63a29e659e71ce85b44d84d1f217edc154ee752356960c8d73e2a317276.webp" 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>Tools like: Foundry, Hardhat, Brownie, Apeworx, Remix, Truffle</p><p>The next step he takes is to download the code to his local environment and bring his tools. For working with ENS, Tincho git-cloned the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ensdomains/ens">GitHub repo</a> and then created a foundry project. ENS is a hardhat-based project, but Tincho has been working with Foundry recently due to its speed, so he spun up a small Foundry project where he would run little tests against the repo.</p><h2 id="h-3-get-your-scope" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">3. Get your scope</h2><p>The next step Tincho takes is to use either <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://cloc.sourceforge.net/">cloc</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ConsenSys/solidity-metrics">solidity metrics</a> to get the scope of the project he is going to audit, and place them into a sheets/excel folder organized by size.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3d119eb4d97de4ddb34eb12206b5e3fa1b81ef8830f19cbd463bdb6e33606f55.webp" 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>Example Scoping Phase</p><p>On the right, he will make a <code>status</code> column so he can keep track of what he has audited. He usually starts from the least complex or the “little legos” and works his way up. Understanding the smaller pieces gives him context on how everything fits together when he gets to the more complex contracts.</p><p>Additionally, if your audit calls for only reading specific contracts, you may remove them from your sheet, so you know what you shouldn’t spend your time on. A file like this is especially important when working with teams, as you can know what everyone is working on.</p><h2 id="h-4-start-taking-notes-onin-the-code" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">4. Start taking notes on/in the code</h2><p>Now that you know what the code is doing, you should constantly be thinking, “how can I break this?” or “does this do what it should be doing?”. Tincho will leave comments right in the code to let him know he was there.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/faca40e8fc090c39808db250e732c05584bdd99a56616c24ebac98505dc8c33d.webp" 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>The `// e` comments are examples of leaving notes for yourself in the future</p><p>Additionally, he has a file that he uses just to dump ideas, thoughts, and keep track of any issues/findings he has.</p><h2 id="h-5-remember-audits-are-time-boxed" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">5. Remember, audits are time-boxed</h2><p>It’s very easy to fall deep down the rabbit hole on something, and you can always re-read a line of code and re-validate something works the way it can. But you’ll need to remember to come up for air.</p><h2 id="h-6-keep-a-line-of-communication-with-the-developers" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">6. Keep a line of communication with the developers</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3bb1b0e005e81838743011bd42f8a9cd0b3dcb09d8d38210a7a882e74c02db60.gif" 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>Maybe you should have 2 phones too</p><p>Developers have worked on this code for much longer than you have and you ever will have. They have more context than you ever will have. Use the developers who wrote the code to your advantage and ask them questions.</p><p>Additionally, if you’re a developer and you’re getting an audit, remember, ultimately, you are responsible for your code, so making yourself available to the auditor will make their lives much easier.</p><h2 id="h-7-audit-a-lot" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">7. Audit a lot</h2><p>The best way to start having a “feel” for vulnerabilities is to do a lot of audits, read audit reports, read post-mortems, and digest as much security-related information as you can.</p><p>Every auditor on the planet, at some point, will miss something. Don’t let that stop you. Always focus on doing the best job that you can, and never become content with your skill level.</p><p>Always be growing and learning.</p><blockquote><p>As they say:Repetition is the mother of skill.</p></blockquote><p>Some of my favorite resources:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/@PatrickAlphaC/videos">My YouTube</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://weekinethereumnews.com/">WeekInEthereum</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rekt.news/">Rekt</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.trailofbits.com/">Trail Of Bits Blog</a></p></li></ul><h2 id="h-8-take-a-lot-of-time-to-write-your-reports" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">8. Take a lot of time to write your reports</h2><p>If you find a million vulnerabilities, but you don’t communicate them effectively, you essentially didn’t find any vulnerabilities.</p><p>An audit is more than just the report; you are responsible for keeping your client safe and teaching them how to be more secure with their code. So make sure you take the time to write reports that articulate issues so that they can learn.</p><h2 id="h-9-remember-an-audit-is-more-than-the-report" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">9. Remember, an audit is more than the report</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/58c12ad9abe2589911d212cfa1153e29d8b64a9e063d36ba7a3ccf02eb245773.webp" 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>Leaderboard of <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rekt.news/leaderboard/">rekt.news</a></p><p>I finished the call by asking, “What happens if you audit a contract, and the protocol gets hacked, and you end up on rekt?”.</p><p>A question a lot of auditors have that makes them nervous. He responded by saying:</p><ol><li><p>An audit is more than whether or not you find all the bugs</p></li><li><p>An audit should provide value regardless</p></li><li><p>Every auditor on the planet who is worth their salt doesn&apos;t have a perfect track record</p></li></ol><p>When auditing, you should be not only finding bugs but:</p><ol><li><p>Teaching best practices</p></li><li><p>Helping them understand attack vectors</p></li><li><p>Showing effective testing practices</p></li></ol><p>It’s your job to level up the client as a group **and **find bugs. And no matter how amazing of an auditor you are, sometimes a protocol will get hacked. You need to take accountability, learn why you made this mistake, and learn and grow from it. Ideally, this doesn’t happen, but when it does, do your best to help the client with any mitigation.</p><h2 id="h-summary" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Summary</h2><p>There is no one silver bullet to auditing, but hopefully, seeing behind the curtain gives you more context as to what goes on in an audit and how you can start your journey!</p><p>😸😸Follow Patrick!😸😸</p><p>Book a smart contract audit: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cyfrin.io/">Cyfrin</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/@PatrickAlphaC/videos">https://www.youtube.com/@PatrickAlphaC/videos</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/patrickalphac">https://twitter.com/patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/@patrickalphac">https://medium.com/@patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.tiktok.com/@patrickalphac">https://www.tiktok.com/@patrickalphac</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/channel/UCMHHNgcezTnfrJUM1vIiZlQ">https://www.youtube.com/channel/UCMHHNgcezTnfrJUM1vIiZlQ</a></p>]]></content:encoded>
            <author>patrickalphac-old@newsletter.paragraph.com (Patrick Collins)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/b4f5900e270ff11c88eee1ba6a39a20d07b3ea5657615e2a2a1a364fb2479e86.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Solidity vs. Vyper | EVM Smart Contract Language Comparisons]]></title>
            <link>https://paragraph.com/@patrickalphac-old/solidity-vs-vyper-evm-smart-contract-language-comparisons</link>
            <guid>uhrYtJnM4DBivFVTbhp3</guid>
            <pubDate>Sun, 26 Feb 2023 19:54:42 GMT</pubDate>
            <description><![CDATA[We compare gas optimizations, developer experience and more between the most popular smart contract languages Solidity & Vyper and use Huff & Yul as benchmarks.Originally Posted in blog.chain.link This article was written based on information from September 2022. Special thanks to 0xKitsune, Hari, Doggie B, Alex Beregszaszi, Zubin Pratap, and Sudo Init Vyper. Video: IntroductionRecently, there has been a lot of debate about “the best” smart contract language, with maxis on each side advocatin...]]></description>
            <content:encoded><![CDATA[<h2 id="h-we-compare-gas-optimizations-developer-experience-and-more-between-the-most-popular-smart-contract-languages-solidity-and-vyper-and-use-huff-and-yul-as-benchmarks" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">We compare gas optimizations, developer experience and more between the most popular smart contract languages Solidity &amp; Vyper and use Huff &amp; Yul as benchmarks.</h2><p><em>Originally Posted in </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.chain.link/solidity-vs-vyper/"><em>blog.chain.link</em></a></p><p><em>This article was written based on information from September 2022. Special thanks to</em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/0xKitsune"> <em>0xKitsune</em></a><em>, </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/_hrkrshnn"><em>Hari</em></a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/fubuloubu"><em>Doggie B</em></a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/alexberegszaszi"><em>Alex Beregszaszi</em></a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/ZubinPratap"><em>Zubin Pratap</em></a>, and<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/big_tech_sux"> <em>Sudo Init Vyper</em></a><em>.</em></p><p>Video:</p><div data-type="youtube" videoId="sbc74oU94FM">
      <div class="youtube-player" data-id="sbc74oU94FM" style="background-image: url('https://i.ytimg.com/vi/sbc74oU94FM/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=sbc74oU94FM">
          <img src="{{DOMAIN}}/editor/youtube/play.png" class="play"/>
        </a>
      </div></div><h2 id="h-introduction" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Introduction</h2><p>Recently, there has been a lot of debate about “the best” smart contract language, with maxis on each side advocating for their chosen language.</p><p>I’m here to answer the main question at the bottom of this debate: <strong>Which smart contract language should I use?</strong></p><p>To get to the bottom of the question, we’re going to talk about tooling and useability before considering one of the main questions for any smart contract developer: gas optimization. Specifically, we are going to look at four<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/developers/docs/evm/"> EVM</a> languages (the languages that work on chains like<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/"> Ethereum</a>,<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.avax.network/"> Avalanche</a>,<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://polygon.technology/"> Polygon</a>, etc.):<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/v0.8.16/"> Solidity</a>,<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://vyper.readthedocs.io/en/stable/index.html"> Vyper</a>,<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.huff.sh/"> Huff</a>, and<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/latest/yul.html"> Yul</a>. Sorry<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.solana.com/developing/on-chain-programs/developing-rust"> Rust</a>, you’ll have to wait your turn for an article covering non-EVM chains.</p><p>But first, a spoiler alert.</p><p><em>Solidity, Vyper, Huff, and Yul are all great languages that get the job done. Solidity and Vyper are fantastic high-level languages that most people should use. If you’re interested in writing near-assembly code, Yul and Huff do the job.</em></p><p>So guess what, if you’re stuck on picking one,<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://justflipacoin.com/"> flip a coin</a>: You’ll be successful whichever language you pick, I promise. If you’re new to smart contract programming languages, you can do great things with whichever languages you like best or whichever one you choose at random.</p><p>Additionally, these languages change constantly, and you could easily cherry-pick smart contracts and data to make different languages seem better or worse. Keep this in mind when we get to the gas optimization comparisons. We’ve chosen a minimal contract for comparison, if you think you have a better example, we’d love to see it!</p><p>Now, if you’re a veteran of this space, let’s go deep under the hood of these languages. Prepare to geek out.</p><h2 id="h-players" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Players</h2><p>The four languages that we are going to be looking at are as follows:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/v0.8.16/">Solidity</a>: Currently the most popular language by<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://impermax.medium.com/defi-explained-what-is-tvl-9800eda80b0b"> DeFi TVL</a>. High-level and similar to JavaScript.</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://vyper.readthedocs.io/en/stable/index.html">Vyper</a>: Currently the second most popular language by DeFi TVL. High-level and similar to Python.</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://huff.sh/">Huff</a>: A low-level language similar to Assembly.</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/latest/yul.html">Yul</a>: A low-level language similar to Assembly that comes built-in with Solidity (although some argue it’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ethereum/solidity/issues/13247">still too high level</a>).</p></li></ul><h2 id="h-why-these-four" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why These Four?</h2><p>We are using these four languages as they are all EVM-compatible, with Solidity and Vyper being the top two most popular languages. I’ve added Yul as it’s unfair to make gas optimization comparisons with Solidity without considering Yul. We’ve added Huff because we wanted to benchmark to a language that is nearly identical to writing in opcodes but isn’t Yul.</p><p>As far as the EVM goes, after Vyper and Solidity, third, fourth, and fifth are leaps and bounds down in popularity. Sorry to the languages that didn’t make this comparison; the adoption just isn’t there. However, many promising smart contract languages are on the rise, and I’m looking forward to trying them out in the future.</p><h2 id="h-the-current-landscape" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Current Landscape</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ed2b41ffe2d96fc6f802aa95e99dd9657cacb8ddbdecfece29e26fb3cf743c53.webp" 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>From <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://defillama.com/">DefiLlama</a></p><p>According to<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://defillama.com/languages"> DefiLlama</a>, in the DeFi space, Solidity smart contracts secure 87% of TVL, while Vyper smart contracts secure 8%.</p><p>So if pure popularity is what you’re looking for, you need not look further than Solidity.</p><h2 id="h-comparing-the-same-contract" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Comparing the Same Contract</h2><p>Now let’s get into what each language looks like and then compare their gas performance.</p><p>Here are four *nearly *identical contracts written in each language. They all do approximately the same thing, They all:</p><ol><li><p>Have a private number (uint256) at storage slot 0.</p></li><li><p>Have a function with the <code>readNumber()</code><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.stackexchange.com/q/135205/57451"> function signature</a> that reads what’s at storage slot 0.</p></li><li><p>Allow you to update that number with a <code>storeNumber(uint256)</code> function signature.</p></li></ol><p>That’s it. Here are those contracts.</p><p><em>All the code we’ve used to compare languages is located in</em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PatrickAlphaC/sc-language-comparison"> <em>this GitHub repo</em></a><em>.</em></p><h2 id="h-solidity" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solidity</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f71d861a76db78dc70a8153de2a2dab61695252268ccd6b862a7d98d0ee4f1b0.webp" 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>Solidity Code</p><h2 id="h-vyper" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Vyper</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d82a8af9f9af02afaba6d59e6602bb662212b30dc7ed6909d39beb4992a8e527.webp" 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>Vyper Code</p><h2 id="h-huff" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">♞ Huff</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f56d1ef921eb8777119d10b9bc89743b4d1b5963a6555d40c57bc1588dcaebe7.webp" 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>Huff Code</p><h2 id="h-yul" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Yul</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1346574cf8c55a4a9f1416167900d68b1d25b03b0868d89361bbe13b7ee9b3cb.webp" 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>Yul Code</p><h2 id="h-developer-experience" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Developer Experience</h2><p>Just by looking at these four images, we can start to see a picture of how each language feels to write. As far as developer experience goes, <strong>it’s substantially quicker to write Solidity and Vyper code.</strong> This makes a lot of sense: those languages are higher level, while Yul and Huff are meant to be low-level code. For this reason alone, it’s easy to see why so many people have adopted Vyper and Solidity (as well as the fact that they have each been around much longer).</p><p>Focusing on Vyper and Solidity for a second, you can see that Vyper draws inspiration from Python and Solidity from JavaScript and Java. So if you like the feel of one of those languages, great — use it.</p><p>Vyper is meant to be a<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://vyper.readthedocs.io/en/stable/index.html#principles-and-goals"> minimalistic, easily audited programming language</a>, while Solidity is meant to be a general-purpose smart contract language. The experience of coding definitely feels like it too on a syntactic level, but I’ll let you make up your mind on this subjective point.</p><p>I will not go into tooling too much, as most of these languages have similar tooling. Most of the main frameworks, including<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/"> Hardhat</a>, ape, Titanoboa,<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/eth-brownie/brownie"> Brownie</a>, and<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/foundry-rs/foundry"> Foundry</a>, have Vyper and Solidity support. Solidity has “priority citizenship” with most of these frameworks, whereas Vyper needs to<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.npmjs.com/package/@nomiclabs/hardhat-vyper"> use a plugin</a> to work with tools like Hardhat. However, Titanoboa is built to work specifically and only with Vyper, and most tooling is easy enough to use with either.</p><h2 id="h-which-smart-contract-language-is-more-gas-optimized" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Which Smart Contract Language Is More Gas-Optimized?</h2><p>Now for the main event. When comparing the gas performance of smart contracts, there are two main things to keep in mind:</p><ol><li><p>Contract creation gas costs</p></li><li><p>Runtime gas costs</p></li></ol><p>How you implement a smart contract can have a major impact on these factors. You could, for example, store a massive array in the code of your contract, making it expensive to deploy but cheaper to run a function with. Or, you could have your function generate the array on the fly, making the contract cheaper to deploy but more expensive to run.</p><p>So, let’s look at those four contracts and compare their contract creation gas costs against their runtime gas costs. You can find all my code on this, including the frameworks and tooling used to compare them, in my<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PatrickAlphaC/sc-language-comparison"> sc-language-comparison repo.</a></p><h2 id="h-gas-cost-comparisons-summary" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Gas Cost Comparisons Summary</h2><p>Here is how we compiled the contracts for this section:</p><pre data-type="codeBlock" text="vyper src/vyper/VSimpleStorage.vyhuffc src/huff/HSimpleStorage.huff -bsolc --strict-assembly --optimize --optimize-runs 20000 
yul/YYSimpleStorage.yul --binsolc --optimize --optimize-runs 20000 src/yulsol/YSimpleStorage.sol --binsolc --optimize --optimize-runs 20000 src/solidity/SSimpleStorage.sol --bin
"><code>vyper <span class="hljs-attribute">src</span>/vyper/VSimpleStorage<span class="hljs-selector-class">.vyhuffc</span> <span class="hljs-attribute">src</span>/huff/HSimpleStorage<span class="hljs-selector-class">.huff</span> -bsolc <span class="hljs-attr">--strict-assembly</span> <span class="hljs-attr">--optimize</span> <span class="hljs-attr">--optimize-runs</span> <span class="hljs-number">20000</span> 
yul/YYSimpleStorage<span class="hljs-selector-class">.yul</span> <span class="hljs-attr">--binsolc</span> <span class="hljs-attr">--optimize</span> <span class="hljs-attr">--optimize-runs</span> <span class="hljs-number">20000</span> <span class="hljs-attribute">src</span>/yulsol/YSimpleStorage<span class="hljs-selector-class">.sol</span> <span class="hljs-attr">--binsolc</span> <span class="hljs-attr">--optimize</span> <span class="hljs-attr">--optimize-runs</span> <span class="hljs-number">20000</span> <span class="hljs-attribute">src</span>/solidity/SSimpleStorage<span class="hljs-selector-class">.sol</span> <span class="hljs-attr">--bin</span>
</code></pre><p><em>Note: I could have used the –via-ir flag for the Solidity compilations as well. Also note, Vyper and Solidity add “Metadata” to the end of their contracts. This accounts for a small addition in overall gas costs, but not enough to change the rankings below. I’ll talk about this more in the metadata section.</em></p><p>Results:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0c86f4fadbda11add5f2efddd284554056d8ef5cff6d6c0d234607e4a5731caf.webp" 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>Creation Costs</p><p>As we can see, lower-level languages like Huff and Yul are more gas efficient than Vyper and Solidity, but why is that? Vyper seems more efficient than Solidity, and we have this new “Sol and Yul” section. Well, that’s because you can write Yul *inside *Solidity. Yul was created as a language for Solidity developers to write in when they needed to get closer to machine code.</p><p>So in the chart above, we compare raw Yul, raw Solidity, and a Solidity-Yul mix. The Solidity-Yul version of our code looks like this:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6dcd6fbb52e98c22b0105313fabbea774aec9bfa498202cc4c55f488db4ca93f.webp" 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>SolYul</p><p>You’ll see an example later where this inline-Yul makes a **major **difference in gas costs. We’ll look at why these gas differences exist later, but now let’s look at the gas costs associated with a single test in<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/foundry-rs/foundry"> Foundry</a>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6ec04c2217f5722d988aeaf6823c1290ff8d395d1c305e97539959121e4bd45b.webp" 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>Foundry Test</p><p>This will test the gas cost of storing the number 77 in storage, and then reading the number from storage. Here are the results of running this test.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6fac3559fb49a87239e0a78f9d30371ac7bc1922b32f4bafd14e10312270cd4b.webp" 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>Runtime Gas Costs</p><p>We didn’t have data for Yul since we’d have to make a Yul-Foundry plugin, which I didn’t want to do — and I’d bet the results would be similar to Huff anyway. Remember that this is the gas cost of running the whole testing function, not just the individual functions.</p><h2 id="h-gas-cost-comparisons" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Gas Cost Comparisons</h2><p>Ok, let’s analyze this data. The first question we need to answer is: Why is Huff and Yul contract creation so much more gas efficient than Vyper and Solidity? Well, we can find that answer by looking directly at the bytecode of these contracts.</p><p>When you compile a contract, it is usually split into two or three different parts.</p><ol><li><p>Contract creation code</p></li><li><p>Runtime code</p></li><li><p>Metadata (optional)</p></li></ol><p>For this section, it’s important to understand the basics of opcodes. OpenZeppelin’s blog on<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.openzeppelin.com/deconstructing-a-solidity-contract-part-i-introduction-832efd2d7737/"> deconstructing a contract</a> is a great starting point.</p><h2 id="h-contract-creation-code" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Contract Creation Code</h2><p>The contract creation code is the first section of the bytecode that tells the EVM to stick that contract on-chain. You can typically find it by looking for the CODECOPY opcode (39) in the resulting binary and then finding where it sticks it on-chain and returns with the RETURN opcode (f3), and ends the call.</p><pre data-type="codeBlock" text="Huff:
602f8060093d393df3Yul:
603e80600c6000396000f3feVyper:
61006b61000f60003961006b6000f3Solidity:
6080604052348015600f57600080fd5b5060ac8061001e6000396000f3feSolidity-Yul:
608060405234801561001057600080fd5b5060bc8061001f6000396000f3fe
"><code><span class="hljs-section">Huff:</span>
<span class="hljs-section">602f8060093d393df3Yul:</span>
<span class="hljs-section">603e80600c6000396000f3feVyper:</span>
<span class="hljs-section">61006b61000f60003961006b6000f3Solidity:</span>
<span class="hljs-section">6080604052348015600f57600080fd5b5060ac8061001e6000396000f3feSolidity-Yul:</span>
608060405234801561001057600080fd5b5060bc8061001f6000396000f3fe
</code></pre><p>You’ll also notice a lot of fe opcodes, which is the INVALID opcode. Solidity adds these as markers to show the difference between runtime, contract creation, and metadata code. f3f3 is the RETURNRETURN opcode, and is usually the end of a function or context.</p><p>You might think that because Yul-Solidity has the largest contract creation bytecode and Huff has the smallest, that’s the reason why Huff is the cheapest and Yul-Solidity is the most expensive. But when you copy the entire codebase and stick it on-chain, the codebase size makes a big difference and is the main determining factor. However, this contract creation code does give us an eye into how each of these compilers think, and will give us good insight into how they will compile our contracts.</p><h2 id="h-how-to-read-the-opcodes-and-stack" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How to Read the Opcodes and Stack</h2><p>Now, the EVM is a<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.evm.codes/about"> stack-based machine</a>, meaning that the majority of “stuff” you do is pushing and pulling stuff off a<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.geeksforgeeks.org/stack-data-structure/"> stack</a>. You’ll see to the left we have the<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.evm.codes/"> opcodes</a>, and to the right we have two slashes (//) notating that they are a comment, and what the stack looks like after executing the opcode on the same line, with the top of the stack to the left, and the bottom of the stack to the right.</p><h2 id="h-huff-explained" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Huff Explained</h2><p>The Huff contract creation does just about the most minimal stuff it can do. It grabs the code you wrote, and returns it on-chain.</p><pre data-type="codeBlock" text="PUSH 0x2f        // [2f]
DUP1             // [2f, 2f]
PUSH 0x09        // [09, 2f, 2f]
RETURNDATASIZE   // [0, 09, 2f, 2f]
CODECOPY         // [2f]
RETURNDATASIZE   // [0, 2f]
RETURN           // []
"><code>PUSH <span class="hljs-number">0x2f</span>        <span class="hljs-comment">// [2f]</span>
DUP1             <span class="hljs-comment">// [2f, 2f]</span>
PUSH <span class="hljs-number">0x09</span>        <span class="hljs-comment">// [09, 2f, 2f]</span>
RETURNDATASIZE   <span class="hljs-comment">// [0, 09, 2f, 2f]</span>
CODECOPY         <span class="hljs-comment">// [2f]</span>
RETURNDATASIZE   <span class="hljs-comment">// [0, 2f]</span>
RETURN           <span class="hljs-comment">// []</span>
</code></pre><h2 id="h-yul-explained" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Yul Explained</h2><p>Yul does the same, it uses a few different opcodes, but essentially, it just puts your code on-chain with as few opcodes as possible, and one INVALID opcode.</p><pre data-type="codeBlock" text="PUSH 0x3e  // [3e]
DUP1       // [3e, 3e]
PUSH 0x0c  // [0c, 3e, 3e]
PUSH 0x0   // [0, 0c, 3e, 3e]
CODECOPY   // [3e]
PUSH 0x0   // [0, e3]
RETURN     // []
INVALID    // []
"><code>PUSH <span class="hljs-number">0x3e</span>  <span class="hljs-comment">// [3e]</span>
DUP1       <span class="hljs-comment">// [3e, 3e]</span>
PUSH <span class="hljs-number">0x0c</span>  <span class="hljs-comment">// [0c, 3e, 3e]</span>
PUSH <span class="hljs-number">0x0</span>   <span class="hljs-comment">// [0, 0c, 3e, 3e]</span>
CODECOPY   <span class="hljs-comment">// [3e]</span>
PUSH <span class="hljs-number">0x0</span>   <span class="hljs-comment">// [0, e3]</span>
RETURN     <span class="hljs-comment">// []</span>
INVALID    <span class="hljs-comment">// []</span>
</code></pre><h2 id="h-vyper-explained" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Vyper Explained</h2><p>Vyper is pretty much the same.</p><pre data-type="codeBlock" text="PUSH2 0x06B  // [06B]
PUSH2 0x0F   // [0F, 06B]
PUSH1 0x0    // [0, 0F, 06B]
CODECOPY     // []
PUSH2 0x06B  // [06B]
PUSH1 0x0    // [0, 06B]
RETURN       // []
"><code>PUSH2 <span class="hljs-number">0x06B</span>  <span class="hljs-comment">// [06B]</span>
PUSH2 <span class="hljs-number">0x0F</span>   <span class="hljs-comment">// [0F, 06B]</span>
PUSH1 <span class="hljs-number">0x0</span>    <span class="hljs-comment">// [0, 0F, 06B]</span>
CODECOPY     <span class="hljs-comment">// []</span>
PUSH2 <span class="hljs-number">0x06B</span>  <span class="hljs-comment">// [06B]</span>
PUSH1 <span class="hljs-number">0x0</span>    <span class="hljs-comment">// [0, 06B]</span>
RETURN       <span class="hljs-comment">// []</span>
</code></pre><h2 id="h-solidity-explained" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solidity Explained</h2><p>Now let’s take a look at the Solidity opcodes.</p><pre data-type="codeBlock" text="// Free Memory Pointer
PUSH1 0x80   // [80]
PUSH1 0x40   // [40]
MSTORE       // []// Check msg.value
CALLVALUE    // [msg.value]
DUP1         // [msg.value, msg.value]
ISZERO       // [msg.value == 0, msg.value]
PUSH1 0xF    // [F, msg.value == 0, msg.value]
JUMPI        // [msg.value] Jump to JUMPDEST if value is not sent// We only reach this part if msg.value has value
PUSH1 0x0    // [0, msg.value]
DUP1         // [0, 0, msg.value]
REVERT       // [msg.value]// Finally, put our code on-chain
JUMPDEST     // [msg.value]
POP          // []
PUSH1 0xAC   // [AC]
DUP1         // [AC, AC]
PUSH2 0x1E   // [1E, AC, AC]
PUSH1 0x0    // [0, 1E, AC, AC]
CODECOPY     // [AC]
PUSH1 0x0    // [0, AC]
RETURN       // []
INVALID      // []
"><code><span class="hljs-comment">// Free Memory Pointer</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x80</span>   <span class="hljs-comment">// [80]</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x40</span>   <span class="hljs-comment">// [40]</span>
<span class="hljs-selector-tag">MSTORE</span>       <span class="hljs-comment">// []// Check msg.value</span>
<span class="hljs-selector-tag">CALLVALUE</span>    <span class="hljs-comment">// [msg.value]</span>
<span class="hljs-selector-tag">DUP1</span>         <span class="hljs-comment">// [msg.value, msg.value]</span>
<span class="hljs-selector-tag">ISZERO</span>       <span class="hljs-comment">// [msg.value == 0, msg.value]</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">xF</span>    <span class="hljs-comment">// [F, msg.value == 0, msg.value]</span>
<span class="hljs-selector-tag">JUMPI</span>        <span class="hljs-comment">// [msg.value] Jump to JUMPDEST if value is not sent// We only reach this part if msg.value has value</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x0</span>    <span class="hljs-comment">// [0, msg.value]</span>
<span class="hljs-selector-tag">DUP1</span>         <span class="hljs-comment">// [0, 0, msg.value]</span>
<span class="hljs-selector-tag">REVERT</span>       <span class="hljs-comment">// [msg.value]// Finally, put our code on-chain</span>
<span class="hljs-selector-tag">JUMPDEST</span>     <span class="hljs-comment">// [msg.value]</span>
<span class="hljs-selector-tag">POP</span>          <span class="hljs-comment">// []</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">xAC</span>   <span class="hljs-comment">// [AC]</span>
<span class="hljs-selector-tag">DUP1</span>         <span class="hljs-comment">// [AC, AC]</span>
<span class="hljs-selector-tag">PUSH2</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x1E</span>   <span class="hljs-comment">// [1E, AC, AC]</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x0</span>    <span class="hljs-comment">// [0, 1E, AC, AC]</span>
<span class="hljs-selector-tag">CODECOPY</span>     <span class="hljs-comment">// [AC]</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x0</span>    <span class="hljs-comment">// [0, AC]</span>
<span class="hljs-selector-tag">RETURN</span>       <span class="hljs-comment">// []</span>
<span class="hljs-selector-tag">INVALID</span>      <span class="hljs-comment">// []</span>
</code></pre><p>Solidity does a lot more stuff. The first thing Solidity does is create what’s called a<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/v0.8.16/assembly.html?highlight=free%20memory%20pointer#memory-management"> Free Memory Pointer</a>. In order to create dynamic arrays in memory, you need to keep track of which parts of your memory are free to use. We don’t use this free memory pointer in our contract construction code, but it’s one of the first things it always does. This is one of the first main differences between languages we’ve uncovered: memory management. Each language handles memory differently.</p><p>Next, the Solidity compiler looks at your code and notices that you didn’t specify a constructor to be payable. So to make sure you don’t shoot yourself in the foot and accidentally send ETH with your contract creation, it uses the <code>CALLVALUE</code> opcode and starts a check to make sure you don’t send any tokens with your contract creation. This brings us to the second main difference between languages: They each have different checks and protections against common issues.</p><p>Finally, Solidity does what the other languages do: It sticks your contract on-chain.</p><p>We’re going to skip Solidity-Yul this works in a similar way to Solidity on its own.</p><h2 id="h-checks-and-protections" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Checks and Protections</h2><p>It looks like Solidity is “safer” in this sense since it has many more protections than the rest of the languages. However, if you were to add a constructor to your Vyper code and then re-compile, you’d notice something different.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/042d3694117341970db8b58faa90659ebd0eb1e8145feccc743bfd13bcf379cf.webp" 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>Vyper with Constructor</p><p>Compile this and your contract creation code looks more like Solidity’s.</p><pre data-type="codeBlock" text="// First, we check the callvalue, and jump to a JUMPDEST much later in the opcodes
CALLVALUE
PUSH2 0x080
JUMPI
// This part is identical to the original compilation
PUSH2 0x06B
PUSH2 0x014
PUSH1 0x0
CODECOPY
PUSH2 0x06B
PUSH1 0x0
RETURN
"><code><span class="hljs-comment">// First, we check the callvalue, and jump to a JUMPDEST much later in the opcodes</span>
<span class="hljs-built_in">CALLVALUE</span>
PUSH2 <span class="hljs-number">0x080</span>
JUMPI
<span class="hljs-comment">// This part is identical to the original compilation</span>
PUSH2 <span class="hljs-number">0x06B</span>
PUSH2 <span class="hljs-number">0x014</span>
PUSH1 <span class="hljs-number">0x0</span>
CODECOPY
PUSH2 <span class="hljs-number">0x06B</span>
PUSH1 <span class="hljs-number">0x0</span>
RETURN
</code></pre><p>It still doesn’t have the memory management that Solidity has, but you’ll see that it does a check for <code>CALLVALUE</code> with a constructor. If you make the constructor payable and re-compile, that check will then again go away.</p><p>So we can come to two conclusions just by looking at these contract creation setups:</p><ol><li><p>In Huff and Yul, you’ll need to be explicit about checks and write them yourself.</p></li><li><p>Solidity and Vyper will do checks for you, with Solidity potentially doing more out of the box.</p></li></ol><p>That is going to be one of the biggest tradeoffs between languages: What checks are they performing under the hood? Writing in Huff and Yul will be more effective since both languages are not meant to do anything under the hood. So of course your code will be more gas efficient, but it’ll be tougher for you to keep track of everything that is going on.</p><h2 id="h-runtime-code" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Runtime Code</h2><p>Now that we have some familiarity with what’s going on under the hood, we can look at how the different functions of the contracts perform, and why they perform the way they do.</p><p>Let’s look at calling the storeNumber() function, with the value 77 for each language. I’m getting the opcode by walking through the<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://book.getfoundry.sh/forge/debugger"> Forge debug feature</a> with a command like forge test –debug “testStorageAndReadSol”. I also used the<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/huff-language/vscode-huff"> Huff VSCode extension</a>.</p><h2 id="h-huff-explained" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Huff Explained</h2><pre data-type="codeBlock" text="// First, we get the function selector of the call and jump to the code for our storeNumber function
PUSH 0x0         // [0]                                                                                                                                              
CALLDATALOAD     // [b6339418] The function selector for storing                                                                                                                                   
PUSH 0xe         // [e, b6339418]                                                                                   
SHR              // [b6339418]                                                                                                                                               
DUP1             // [b6339418, b6339418]                                                                                                                                              
PUSH 0xb6339418  // [b6339418, b6339418, b6339418]                                                                                      
EQ               // [true, b6339418]                                                                                                                                              
PUSH 0x1c        // [1c, true, b6339418]                                                                                  
JUMPI            // [b6339418]
                                                                                                                                           
// We skip a bunch of opcodes since we jumped
// We place the 77 in storage, and end the call
JUMPDEST         // [b6339418]                                                                                                                                           
PUSH 0x4         // [4, b6339418]                                                                                
CALLDATALOAD     // [4d, b6339418] We load 77 from the calldata                                                                                                                                             
PUSH 0x0         // [0, 4d, b6339418]                                                                                                                                          
SSTORE           // [b6339418] Place the 77 in storage 
STOP             // [b6339418] End call
"><code><span class="hljs-comment">// First, we get the function selector of the call and jump to the code for our storeNumber function</span>
PUSH <span class="hljs-number">0x0</span>         <span class="hljs-comment">// [0]                                                                                                                                              </span>
<span class="hljs-built_in">CALLDATALOAD</span>     <span class="hljs-comment">// [b6339418] The function selector for storing                                                                                                                                   </span>
PUSH <span class="hljs-number">0xe</span>         <span class="hljs-comment">// [e, b6339418]                                                                                   </span>
SHR              <span class="hljs-comment">// [b6339418]                                                                                                                                               </span>
DUP1             <span class="hljs-comment">// [b6339418, b6339418]                                                                                                                                              </span>
PUSH <span class="hljs-number">0xb6339418</span>  <span class="hljs-comment">// [b6339418, b6339418, b6339418]                                                                                      </span>
EQ               <span class="hljs-comment">// [true, b6339418]                                                                                                                                              </span>
PUSH <span class="hljs-number">0x1c</span>        <span class="hljs-comment">// [1c, true, b6339418]                                                                                  </span>
JUMPI            <span class="hljs-comment">// [b6339418]</span>
                                                                                                                                           
<span class="hljs-comment">// We skip a bunch of opcodes since we jumped</span>
<span class="hljs-comment">// We place the 77 in storage, and end the call</span>
JUMPDEST         <span class="hljs-comment">// [b6339418]                                                                                                                                           </span>
PUSH <span class="hljs-number">0x4</span>         <span class="hljs-comment">// [4, b6339418]                                                                                </span>
<span class="hljs-built_in">CALLDATALOAD</span>     <span class="hljs-comment">// [4d, b6339418] We load 77 from the calldata                                                                                                                                             </span>
PUSH <span class="hljs-number">0x0</span>         <span class="hljs-comment">// [0, 4d, b6339418]                                                                                                                                          </span>
SSTORE           <span class="hljs-comment">// [b6339418] Place the 77 in storage </span>
STOP             <span class="hljs-comment">// [b6339418] End call</span>
</code></pre><p>Interestingly, if we didn’t have the STOP opcode, our Huff code would have actually added a group of opcodes to return the value we just stored, making it more expensive than our Vyper code. But this code still seems very straightforward, so let’s look at how Vyper does it. We are going to skip Yul for now as the results would be pretty similar.</p><h2 id="h-vyper-explained" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Vyper Explained</h2><pre data-type="codeBlock" text="// First, we do a check on the calldata size to make sure we have at least 4 bytes for a function selector
PUSH 0x3        // [3]
CALLDATASIZE    // [3, 24]
GT              // [true]
PUSH 0x000c     // [000c, true]
JUMPI           // []
// Then, we jump to our location, and get the function selector
JUMPDEST
PUSH 0x0        // [0]
CALLDATALOAD    // [b6339418]
PUSH 0xe        // [e, b6339418]
SHR             // [b6339418]
// And we do a check for sending value
CALLVALUE       // [0, b6339418]
PUSH 0x0059     // [59, 0, b6339418]
JUMPI           // [b6339418]
// Value looks good, so we compare selectors, and jump if the selector is something else
PUSH 0xb6339418 // [b6339418, b6339418]
DUP2            // [b6339418, b6339418, b6339418]
XOR             // [0, b6339418]
PUSH 0x0032     // [32, 0, b6339418]
JUMPI           // [b6339418]
// We do a check to make sure the calldata size is big enough for a function selector and a uint256
PUSH 0x24       // [24, b6339418]
CALLDATASIZE    // [24, 24, b6339418]
XOR             // [0, b6339418]
PUSH 0x0059     // [59, 0, b6339418]
JUMPI           // [b6339418]
// Then, we store the variable and end the call
PUSH 0x04       // [4, b6339418]
CALLDATALOAD    // [4d, b6339418]
PUSH 0x0        // [0, 4d, b6339418]
SSTORE          // [b6339418]
STOP
"><code><span class="hljs-comment">// First, we do a check on the calldata size to make sure we have at least 4 bytes for a function selector</span>
PUSH <span class="hljs-number">0x3</span>        <span class="hljs-comment">// [3]</span>
<span class="hljs-built_in">CALLDATASIZE</span>    <span class="hljs-comment">// [3, 24]</span>
GT              <span class="hljs-comment">// [true]</span>
PUSH <span class="hljs-number">0x000c</span>     <span class="hljs-comment">// [000c, true]</span>
JUMPI           <span class="hljs-comment">// []</span>
<span class="hljs-comment">// Then, we jump to our location, and get the function selector</span>
JUMPDEST
PUSH <span class="hljs-number">0x0</span>        <span class="hljs-comment">// [0]</span>
<span class="hljs-built_in">CALLDATALOAD</span>    <span class="hljs-comment">// [b6339418]</span>
PUSH <span class="hljs-number">0xe</span>        <span class="hljs-comment">// [e, b6339418]</span>
SHR             <span class="hljs-comment">// [b6339418]</span>
<span class="hljs-comment">// And we do a check for sending value</span>
<span class="hljs-built_in">CALLVALUE</span>       <span class="hljs-comment">// [0, b6339418]</span>
PUSH <span class="hljs-number">0x0059</span>     <span class="hljs-comment">// [59, 0, b6339418]</span>
JUMPI           <span class="hljs-comment">// [b6339418]</span>
<span class="hljs-comment">// Value looks good, so we compare selectors, and jump if the selector is something else</span>
PUSH <span class="hljs-number">0xb6339418</span> <span class="hljs-comment">// [b6339418, b6339418]</span>
DUP2            <span class="hljs-comment">// [b6339418, b6339418, b6339418]</span>
XOR             <span class="hljs-comment">// [0, b6339418]</span>
PUSH <span class="hljs-number">0x0032</span>     <span class="hljs-comment">// [32, 0, b6339418]</span>
JUMPI           <span class="hljs-comment">// [b6339418]</span>
<span class="hljs-comment">// We do a check to make sure the calldata size is big enough for a function selector and a uint256</span>
PUSH <span class="hljs-number">0x24</span>       <span class="hljs-comment">// [24, b6339418]</span>
<span class="hljs-built_in">CALLDATASIZE</span>    <span class="hljs-comment">// [24, 24, b6339418]</span>
XOR             <span class="hljs-comment">// [0, b6339418]</span>
PUSH <span class="hljs-number">0x0059</span>     <span class="hljs-comment">// [59, 0, b6339418]</span>
JUMPI           <span class="hljs-comment">// [b6339418]</span>
<span class="hljs-comment">// Then, we store the variable and end the call</span>
PUSH <span class="hljs-number">0x04</span>       <span class="hljs-comment">// [4, b6339418]</span>
<span class="hljs-built_in">CALLDATALOAD</span>    <span class="hljs-comment">// [4d, b6339418]</span>
PUSH <span class="hljs-number">0x0</span>        <span class="hljs-comment">// [0, 4d, b6339418]</span>
SSTORE          <span class="hljs-comment">// [b6339418]</span>
STOP
</code></pre><p>We can see that we did a few checks along with storing the value:</p><ol><li><p>Does the calldata have enough bytes for a function selector?</p></li><li><p>Is their value sent with the call?</p></li><li><p>Is the calldata size a function selector + uint256 sized?</p></li></ol><p>All these checks add gas to our computation, but they also mean that we have a greater chance of not shooting ourselves in the foot.</p><h2 id="h-solidity-explained" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solidity Explained</h2><pre data-type="codeBlock" text="// Free Memory Pointer
PUSH 0x80        // [80]
PUSH 0x40        // [40,80]
MSTORE           // []
// msg.value check, jump to function, revert otherwise
CALLVALUE        // [0]
DUP1             // [0,0]
ISZERO           // [true, 0]
PUSH 0x0f        // [0f, true, 0]
JUMPI            // [0]
// Skip reverting code
// We do a check to make sure the calldata size is big enough for a function selector and a uint256
JUMPDEST         // [0]
POP              // []
PUSH 0x04        // [4]
CALLDATASIZE     // [24, 4]
LT               // [false]
PUSH 0x32        // [32, false]
JUMPI            // []
// Find the function selector and jump to it&apos;s code
PUSH 0x00        // [0]
CALLDATALOAD     // [b6339418]
PUSH 0xe0        // [e0, b6339418]
SHR              // [b6339418]
DUP1             // [b6339418, b6339418]
PUSH 0xb6339418  // [b6339418, b6339418, b6339418]
EQ               // [true, b6339418]
PUSH 0x37        // [37, true, b6339418]
JUMPI            // [b6339418]
// Setup the function by checking the calldata size, and setup the stack for the function
JUMPDEST
PUSH 0x47        // [47, b6339418]
PUSH 0x42        // [42, 47, b6339418]
CALLDATASIZE     // [24, 42, 47, b6339418]
PUSH 0x04        // [4, 24, 42, 47, b6339418]
PUSH 0x5e        // [5e, 4, 24, 42, 47, b6339418]
JUMP             // [4, 24, 42, 47, b6339418]
JUMPDEST         // [4, 24, 42, 47, b6339418]
PUSH 0x00        // [0, 4, 24, 42, 47, b6339418]
PUSH 0x20        // [20, 0, 4, 24, 42, 47, b6339418]
DUP3             // [4, 20, 0, 4, 24, 42, 47, b6339418]
DUP5             // [24, 4, 20, 0, 4, 24, 42, 47, b6339418]
SUB              // [20, 20, 0, 4, 24, 42, 47, b6339418]
// See if the calldatasize minus the function selector size is smaller than 32 bytes
SLT              // [false(0), 0, 4, 24, 42, 47, b6339418]
ISZERO           // [true, 0, 4, 24, 42, 47, b6339418]
PUSH 0x6f        // [6f, true, 0, 4, 24, 42, 47, b6339418]
JUMPI            // [0, 4, 24, 42, 47, b6339418]
// Get the 77 value, and jump to the function selector code
JUMPDEST
POP              // [24, 42, 47, b6339418]
CALLDATALOAD     // [4d, 24, 42, 47, b6339418]
SWAP2            // [42, 24, 4d, 47, b6339418]
SWAP1            // [24, 42, 4d, 47, b6339418]
POP              // [42, 4d, 47, b6339418]
JUMP             // [4d, 47, b6339418]
JUMPDEST         // [4d, 47, b6339418]
// Store our 77 value to storage and end the function call
PUSH 0x00        // [0, 4d, 47, b6339418]
SSTORE           // [47, b6339418]
JUMP             // [b6339418]
JUMPDEST         // [b6339418]
STOP
"><code><span class="hljs-comment">// Free Memory Pointer</span>
PUSH <span class="hljs-number">0x80</span>        <span class="hljs-comment">// [80]</span>
PUSH <span class="hljs-number">0x40</span>        <span class="hljs-comment">// [40,80]</span>
MSTORE           <span class="hljs-comment">// []</span>
<span class="hljs-comment">// msg.value check, jump to function, revert otherwise</span>
<span class="hljs-built_in">CALLVALUE</span>        <span class="hljs-comment">// [0]</span>
DUP1             <span class="hljs-comment">// [0,0]</span>
ISZERO           <span class="hljs-comment">// [true, 0]</span>
PUSH <span class="hljs-number">0x0f</span>        <span class="hljs-comment">// [0f, true, 0]</span>
JUMPI            <span class="hljs-comment">// [0]</span>
<span class="hljs-comment">// Skip reverting code</span>
<span class="hljs-comment">// We do a check to make sure the calldata size is big enough for a function selector and a uint256</span>
JUMPDEST         <span class="hljs-comment">// [0]</span>
POP              <span class="hljs-comment">// []</span>
PUSH <span class="hljs-number">0x04</span>        <span class="hljs-comment">// [4]</span>
<span class="hljs-built_in">CALLDATASIZE</span>     <span class="hljs-comment">// [24, 4]</span>
LT               <span class="hljs-comment">// [false]</span>
PUSH <span class="hljs-number">0x32</span>        <span class="hljs-comment">// [32, false]</span>
JUMPI            <span class="hljs-comment">// []</span>
<span class="hljs-comment">// Find the function selector and jump to it's code</span>
PUSH <span class="hljs-number">0x00</span>        <span class="hljs-comment">// [0]</span>
<span class="hljs-built_in">CALLDATALOAD</span>     <span class="hljs-comment">// [b6339418]</span>
PUSH <span class="hljs-number">0xe0</span>        <span class="hljs-comment">// [e0, b6339418]</span>
SHR              <span class="hljs-comment">// [b6339418]</span>
DUP1             <span class="hljs-comment">// [b6339418, b6339418]</span>
PUSH <span class="hljs-number">0xb6339418</span>  <span class="hljs-comment">// [b6339418, b6339418, b6339418]</span>
EQ               <span class="hljs-comment">// [true, b6339418]</span>
PUSH <span class="hljs-number">0x37</span>        <span class="hljs-comment">// [37, true, b6339418]</span>
JUMPI            <span class="hljs-comment">// [b6339418]</span>
<span class="hljs-comment">// Setup the function by checking the calldata size, and setup the stack for the function</span>
JUMPDEST
PUSH <span class="hljs-number">0x47</span>        <span class="hljs-comment">// [47, b6339418]</span>
PUSH <span class="hljs-number">0x42</span>        <span class="hljs-comment">// [42, 47, b6339418]</span>
<span class="hljs-built_in">CALLDATASIZE</span>     <span class="hljs-comment">// [24, 42, 47, b6339418]</span>
PUSH <span class="hljs-number">0x04</span>        <span class="hljs-comment">// [4, 24, 42, 47, b6339418]</span>
PUSH <span class="hljs-number">0x5e</span>        <span class="hljs-comment">// [5e, 4, 24, 42, 47, b6339418]</span>
JUMP             <span class="hljs-comment">// [4, 24, 42, 47, b6339418]</span>
JUMPDEST         <span class="hljs-comment">// [4, 24, 42, 47, b6339418]</span>
PUSH <span class="hljs-number">0x00</span>        <span class="hljs-comment">// [0, 4, 24, 42, 47, b6339418]</span>
PUSH <span class="hljs-number">0x20</span>        <span class="hljs-comment">// [20, 0, 4, 24, 42, 47, b6339418]</span>
DUP3             <span class="hljs-comment">// [4, 20, 0, 4, 24, 42, 47, b6339418]</span>
DUP5             <span class="hljs-comment">// [24, 4, 20, 0, 4, 24, 42, 47, b6339418]</span>
SUB              <span class="hljs-comment">// [20, 20, 0, 4, 24, 42, 47, b6339418]</span>
<span class="hljs-comment">// See if the calldatasize minus the function selector size is smaller than 32 bytes</span>
SLT              <span class="hljs-comment">// [false(0), 0, 4, 24, 42, 47, b6339418]</span>
ISZERO           <span class="hljs-comment">// [true, 0, 4, 24, 42, 47, b6339418]</span>
PUSH <span class="hljs-number">0x6f</span>        <span class="hljs-comment">// [6f, true, 0, 4, 24, 42, 47, b6339418]</span>
JUMPI            <span class="hljs-comment">// [0, 4, 24, 42, 47, b6339418]</span>
<span class="hljs-comment">// Get the 77 value, and jump to the function selector code</span>
JUMPDEST
POP              <span class="hljs-comment">// [24, 42, 47, b6339418]</span>
<span class="hljs-built_in">CALLDATALOAD</span>     <span class="hljs-comment">// [4d, 24, 42, 47, b6339418]</span>
SWAP2            <span class="hljs-comment">// [42, 24, 4d, 47, b6339418]</span>
SWAP1            <span class="hljs-comment">// [24, 42, 4d, 47, b6339418]</span>
POP              <span class="hljs-comment">// [42, 4d, 47, b6339418]</span>
JUMP             <span class="hljs-comment">// [4d, 47, b6339418]</span>
JUMPDEST         <span class="hljs-comment">// [4d, 47, b6339418]</span>
<span class="hljs-comment">// Store our 77 value to storage and end the function call</span>
PUSH <span class="hljs-number">0x00</span>        <span class="hljs-comment">// [0, 4d, 47, b6339418]</span>
SSTORE           <span class="hljs-comment">// [47, b6339418]</span>
JUMP             <span class="hljs-comment">// [b6339418]</span>
JUMPDEST         <span class="hljs-comment">// [b6339418]</span>
STOP
</code></pre><p>There is a lot to unpack here. What are some of the main differences between this and the Huff code?</p><ol><li><p>We set up a free memory pointer.</p></li><li><p>We did a check on the value being sent.</p></li><li><p>We did a check on calldata size for the function selector.</p></li><li><p>We did a check on the size of the uint256.</p></li></ol><p>What about the main differences between Solidity and Vyper?</p><ol><li><p>Free memory pointer setup.</p></li><li><p>Stack was much deeper at some points.</p></li></ol><p>The two of these combined seem to be the rationale behind Vyper being cheaper than Solidity. It’s also interesting that Solidity uses ISZERO for its checks and Vyper uses XOR; both seem to need about the same gas though. It’s these little design differences that make all the difference!</p><p>So we can now see why Huff and Yul are cheaper in gas: they are very specific about doing exactly what you tell them to do, nothing more, whereas Vyper and Solidity try to protect you from doing something silly.</p><h2 id="h-free-memory-pointer" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Free Memory Pointer</h2><p>So what’s the deal with this free memory pointer? It seems to create a big difference in gas consumption regarding Solidity versus Vyper. The free memory pointer is a feature that controls memory management — anytime you add something to your memory array, your free memory pointer just points to the end of it, like so:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d61cbf0c6138cbd07e5af6bc875c4e383b667fc869950a9e3db7576427995a79.webp" 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>Solidity Memory</p><p>This is great since there are data structures like dynamic arrays that we may have to load into memory. With a dynamic array, we don’t know how big it will be, so we will need to know where memory ends.</p><p>In Vyper, there are no dynamic data structures, you are forced to say exactly how big an object like an array will be. Knowing this, Vyper can allocate memory at compile time and not have a free memory pointer.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9990bd85c3403464bef56f43d1490bcc7b96f26ec5ba5af4b6bb72eed96f8f3e.webp" 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>Vyper Memory</p><p>This means that Vyper can be more gas optimized than Solidity when it comes to memory management. The downside is that with Vyper you need to explicitly state the size of your data structures and can’t have dynamic memory. However, the Vyper team actually looks at this as a plus.</p><h2 id="h-dynamic-arrays" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Dynamic Arrays</h2><p>Setting aside the memory stuff for a minute, it’s true that with Vyper you have to declare the bounds of an array. In Solidity, you can declare an array without a size. In Vyper, you can have a dynamic array, but it has to be “bounded”.</p><p>This could be seen as frustrating for the developer experience, however, in Web3 this could also be seen as protection against denial-of-service attacks and prevent massive gas costs in your functions.</p><p>If you have an array that grows too large in size and you iterate over it, it can cost a ton in gas. However, if you explicitly state the bounds of the array, you’ll know exactly what the worst-case performance of your smart contract would be.</p><h2 id="h-solidity-vs-yul-vs-solyul" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solidity vs. Yul vs. SolYul</h2><p>Looking at my chart above, working with Solidity and Yul seems like the worst option since the contract creation code is so much more expensive. This might be the case for smaller projects since Solidity does a few gymnastics to get the Yul going, but what about at scale?</p><p>One of the most popular projects to be written in a Solidity version and then a SolYul version is the<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ProjectOpenSea/seaport"> Seaport</a> project.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/bac08428993aaf9aad6fb7e787eef5f10dc26f9f538929cbd11535f31851bb7c.webp" 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>Seaport Logo</p><p>One of the best aspects of using these languages is that you can run commands to test out the gas effectiveness of each contract directly from the source code. We added a<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ProjectOpenSea/seaport/pull/646/files"> pull request</a> to aid in the command for testing the gas costs of the pure Solidity contracts, as the Sol-Yul contracts have the tests already. The result of this was pretty staggering, and you can see all the data in<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PatrickAlphaC/seaport/blob/added-gas-profiling-for-reference-contracts/gas-report-reference.txt"> gas-report.txt</a> and<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PatrickAlphaC/seaport/blob/added-gas-profiling-for-reference-contracts/gas-report-reference.txt"> gas-report-reference.txt</a>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d4bddf89186a29938d20585c8ee8e55d58f4402d34d4f9ddc21786d8e9feb1a8.webp" 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>Seaport Gas Differences</p><p>On average, the function calls performed 25% better on the SolYul versions, and the contract creation performed 40% better.</p><p>That’s a lot of gas savings. I wonder how much they could have saved in pure Yul? I wonder how much they would have saved in Vyper vs. Sol-Yul?</p><h2 id="h-metadata" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Metadata</h2><p>And finally, metadata. Vyper and Solidity both append some extra “metadata” to the end of their contracts. It’s such a small amount though, that we are going to be basically ignoring it for the comparisons here. You can always manually chop it off (and adjust the marker for how long your Solidity code is), but the Solidity team is also working on a PR where <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ethereum/solidity/pull/13265">you can remove it at compile time.</a></p><h2 id="h-summary" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Summary</h2><p>Here’s my opinion on these languages:</p><ol><li><p>If you’re coding smart contracts, use Vyper or Solidity. They are both high-level languages that will protect you from shooting yourself in the foot by looking at call data size and whether you accidentally sent ETH when you shouldn’t have. They are both great languages, so pick whichever and have fun.</p></li><li><p>Yul and Huff are fantastic learning resources or tools to use if you need super specifically performant code. I don’t recommend most people write in these languages, but I think they are both fantastic to learn and understand. They will each give you a better understanding of the EVM.</p></li><li><p>One of the main differences in gas costs between Solidity and Vyper is the free memory pointer in Solidity — keep this in mind once you get to an advanced level and are looking to understand one of the underlying differences between the tools.</p></li></ol><h2 id="h-looking-forward" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Looking Forward</h2><p>These languages will continue to evolve, and we will likely see more languages pop up too, like the<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.reach.sh/"> Reach programming language</a> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://fe-lang.org/">and fe</a>.</p><p>The Solidity and Vyper teams have worked on an intermediate representation compilation step. The Solidity team has a <code>— via−ir</code> flag in production that will help optimize Solidity code, and the Vyper team has their venom for intermediate representation as well.</p><p>Whichever language you choose, you’ll be able to write some awesome smart contracts. Happy coding!</p>]]></content:encoded>
            <author>patrickalphac-old@newsletter.paragraph.com (Patrick Collins)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/089c4043ad5148b4f32394d1569c41ae48a801904177a03b0b51c137fc609273.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Safe | Lily Pad Look ]]></title>
            <link>https://paragraph.com/@patrickalphac-old/safe-lily-pad-look</link>
            <guid>IBwc8CrLHG2NRPXypDlh</guid>
            <pubDate>Sun, 19 Feb 2023 15:31:12 GMT</pubDate>
            <description><![CDATA[We look at Safe/Gnosis Safe, the most popular programmable smart contract / multi-sig wallet. How to get started, its main uses, and why people should use multi-sig wallets.Be sure to watch our YouTube video on it! Safe: A term that should instantly notify you that the crypto project it’s associated with is bullshit.Except in the case when it’s preceded by the word Gnosis. Gnosis Safe, or as they’re now known just as safe, is the most popular programmable smart contract wallet often used for ...]]></description>
            <content:encoded><![CDATA[<h2 id="h-we-look-at-safegnosis-safe-the-most-popular-programmable-smart-contract-multi-sig-wallet-how-to-get-started-its-main-uses-and-why-people-should-use-multi-sig-wallets" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">We look at Safe/Gnosis Safe, the most popular programmable smart contract / multi-sig wallet. How to get started, its main uses, and why people should use multi-sig wallets.</h2><p>Be sure to watch our YouTube video on it!</p><div data-type="youtube" videoId="LqbWQg5nsaE">
      <div class="youtube-player" data-id="LqbWQg5nsaE" style="background-image: url('https://i.ytimg.com/vi/LqbWQg5nsaE/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=LqbWQg5nsaE">
          <img src="{{DOMAIN}}/editor/youtube/play.png" class="play"/>
        </a>
      </div></div><blockquote><p>Safe: A term that should instantly notify you that the crypto project it’s associated with is bullshit.</p></blockquote><p>Except in the case when it’s preceded by the word Gnosis. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gnosis-safe.io/">Gnosis Safe</a>, or as they’re now known just as safe, is the most popular programmable smart contract wallet often used for its multi-sig (multiple signatures) capabilities and customization with a traditional wallet, also known as an externally owned account (EOA).</p><p>An <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.gnosis-safe.io/learn/gnosis-safe/eoas-vs.-contract-accounts">EOA</a> wallet has a single private key that secures your funds. These are wallets like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://metamask.io/">Metamask</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.ledger.com/">Ledger</a>, or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rainbow.me/">Rainbow</a>. But if you expose or lose that single key, that single point of failure, you’ll lose all your funds faster than a black hat hacker steals from a DeFi protocol. Additionally, the code on some of these wallets can be closed source and we can’t guarantee how secure they actually are.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5b375428041b3a59db36eb8929ef706e756eab04008377a13eb21e4b3a8cfff2.webp" 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>Visual from <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.gnosis-safe.io/learn/gnosis-safe/eoas-vs.-contract-accounts">Safe</a> documentation</p><p>A smart contract account or wallet, on the other hand, is an account controlled by open-source code, and you can customize your account to be more secure, including requiring multiple keys to sign a transaction. These are often known as multi-sig wallets. If you expose one of your private keys, for example, in a two-of-three multi-sig, that exposed key can’t be used to corrupt the system since it can’t initiate a transaction without the other key.</p><p>Since the wallet is a smart contract, you can then replace the bad key with a fresh new key, and your wallet will continue to be safe. These keys connected to a smart contract account can be from Metmask, Ledger, or even other smart contract wallets. The Safe multi-sig wallet is currently the most popular multi-sig wallet out there used by protocols like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.aave.com/">Aave</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://synthetix.io/">Synthetics</a>, and hopefully, you.</p><h2 id="h-getting-started" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Getting Started</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1da64f4e671a6b32062eb2deff55fe912440bf7fad8505af7b1e5fc31d136c91.webp" 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>Multi-sig wallet visual from <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.gnosis-safe.io/learn/gnosis-safe/eoas-vs.-contract-accounts">Safe documentation</a></p><p>If you’re a paranoid hardo, you can first do a quick month-long audit on the code base and then copy-paste one from Source. But if you want, you can also just go to the website and open the app and we’ll go ahead and click Create New Safe. And to create a safe, we’ll need at least one private key. I’m just gonna go ahead and connect my meta mass, but you can use whatever you.</p><p>The Safe documentation and walkthrough makes it really easy to create your own Safe quickly.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cd7197b7df5f9c18950cb0c58b45ead46dcc484016241e6cf5181806e07395ac.webp" 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>Create a new Gnosis-Safe</p><p>You can also create and interact with safes from <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.gnosis-safe.io/learn/safe-tools/sdks">JavaScript</a>, the command line, and more. They have developer SDKs for you to get started working with Safe programmatically.</p><h2 id="h-recommendation" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Recommendation</h2><p>I highly recommend everyone get familiar at least with a 1-of-1 multi-sig. This will get you familiar with smart contract wallets and even adds a layer of protection to your funds. And according to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.com/queries/4779/9386">Dune analytics</a>, the 1 of 1 safes are the most popular out there at the moment.</p><p>This has been a lily pad look at safe multi-sig wallets. Leave a like if you wanna see more videos like this, and we’ll see you next time.</p>]]></content:encoded>
            <author>patrickalphac-old@newsletter.paragraph.com (Patrick Collins)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/ad32b16d403e7ae7ddbf24a66dd5333cfb9c3654e30b7807a54ec1a81427609b.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>