<?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>Ante Finance</title>
        <link>https://paragraph.com/@ante-finance</link>
        <description>undefined</description>
        <lastBuildDate>Tue, 21 Jul 2026 08:53:40 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Ante Test Series #6: Dai Peg Test - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-test-series-6-dai-peg-test-ante-finance-medium</link>
            <guid>dpBMSWX7NBpW48aFjqAE</guid>
            <pubDate>Fri, 10 Jun 2022 21:37:07 GMT</pubDate>
            <description><![CDATA[Hello there and gm frens!! We’re here today to talk about one of our most popular and simple, yet useful tests that one can write, a price peg test. If you missed our last writeup about Olympus, feel free to find it here! One of our community members, waynebruce, wrote a peg test for the Dai stablecoin, Dai Peg Test, a while back, and we’ll go over it today! Dai by MakerDao, was designed to counter one of the problems other cryptocurrencies were having, which was unstable prices. Dai aims to ...]]></description>
            <content:encoded><![CDATA[<p>Hello there and gm frens!! We’re here today to talk about one of our most popular and simple, yet useful tests that one can write, a price peg test. If you missed our last writeup about Olympus, feel free to find it <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/LYkETrkBC98C-SO8xs-9VdUzKvCd4Sqbo6vAjl8-lus">here</a>!</p><p>One of our community members, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/waynebruce0x">waynebruce</a>, wrote a peg test for the Dai stablecoin, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/main/contracts/dai/Ante_DaiPegTest.sol">Dai Peg Test</a>, a while back, and we’ll go over it today!</p><p>Dai by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://makerdao.com/en/">MakerDao</a>, was designed to counter one of the problems other cryptocurrencies were having, which was unstable prices. Dai aims to change that by being a decentralized, unbiased cryptocurrency that is pegged to the US dollar. This brought along the term stablecoin, and as long as the Keepers maintain the 1 US Dollar target price, then the goal has been achieved.</p><p>Now to the Ante Test in question. This turns out to revolve around 1 crucial point, is the price of Dai within reasonable bounds as described by the Maker Protocol and understood by its users.</p><p>To get to that point, let’s start with the <code>checkTestPasses()</code> function:</p><pre data-type="codeBlock" text="function checkTestPasses() public view override returns (bool) {
    (, int256 price, , , ) = priceFeed.latestRoundData();
    return (95000000 &lt; price &amp;&amp; price &lt; 105000000);
}
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkTestPasses</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
    (, <span class="hljs-keyword">int256</span> price, , , ) <span class="hljs-operator">=</span> priceFeed.latestRoundData();
    <span class="hljs-keyword">return</span> (<span class="hljs-number">95000000</span> <span class="hljs-operator">&#x3C;</span> price <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> price <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">105000000</span>);
}
</code></pre><p>We can see that we’ll return true if the price is between 0.95 and 1.05 US Dollars.</p><p>This price we get by using <code>latestRoundData()</code> from Chainlink’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.chain.link/docs/get-the-latest-price/">aggregator interface</a>.</p><p>Moving on up, we see that the constructor for the Ante Test initializes the protocol, Dai, the contract in question, Dai’s address, and the Dai/USD <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9">aggregator</a> deployed by Chainlink.</p><pre data-type="codeBlock" text="constructor() {
    protocolName = &quot;DAI&quot;;
    testedContracts = [DaiAddr];
    priceFeed = AggregatorV3Interface(0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9);    }
"><code>constructor() {
    <span class="hljs-attr">protocolName</span> = <span class="hljs-string">"DAI"</span><span class="hljs-comment">;</span>
    <span class="hljs-attr">testedContracts</span> = [DaiAddr]<span class="hljs-comment">;</span>
    <span class="hljs-attr">priceFeed</span> = AggregatorV3Interface(<span class="hljs-number">0</span>xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9)<span class="hljs-comment">;    }</span>
</code></pre><p>And that’s it to this Dai Peg Ante Test! At it’s core, there’s just 2 important parts to a peg test, the value that the peg needs to be held at, and getting that value.</p><p>What’s interesting here will be analyzing what could cause a failure in this test.</p><p>The first way this test could fail is if DAI’s price fluctuates outside its range of 0.95 and 1.05. If the test is checked at that time, then it can fail. And this has happened before, looking at CoinGecko’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.coingecko.com/en/coins/dai/usd#panel">historical chart for Dai</a>, back in November of 2019 and March of 2020.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/38bced7f9c344339edcc6f61ea7d6d163490fb255d55077f7d642117ec929425.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Value of Dai from Nov 2019 to Feb 2022</p><p>As the price is what determines whether or not the test fails, the second critical piece then is how we fetch the price, in this case, the Chainlink Aggregator. If an attacker were able to manipulate or trick the aggregator to return a value that doesn’t actually represent the true Dai price, than the test could also fail.</p><p>Food for thought anyway, it’s always good to consider what different ways a test can fail and see if we can make sure that these points are carefully considered when writing an Ante Test!</p><p>As the skeleton for this test is relatively basic, it can be expanded to incorporate different types of pegs depending on what is being called for.</p><p>For example, regarding Tether, this <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/main/contracts/tether/Ante_USDTPegTest.sol">Ante Test</a> written by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/raddy">raddy</a> outlines the fact we care more about the dropping of Tether value, so the test is written to only check if its value drops below 0.90 US dollar.</p><p>And then moving even further! This <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/main/contracts/iron/AnteIronPegTest.sol">Iron Peg Holds Test</a> written by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/a-deva">a-deva</a> highlights how we can take a simple peg test and take it even further! This one is a bit more complicated to go through in this post, so we’ll revisit it another time to go deeper into it.</p><p>And that’s it for this week! Please feel free to come and check out the various tests that have already been written in the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests">Ante Community Github</a>. Join us at our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.com/invite/ante">Discord</a> to talk web3, interesting protocols, Ante Tests, or just hang out! And follow us on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a> to see the latest news and updates we have! Till next time everybody!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante Tests Explained: Ribbon Finance - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-tests-explained-ribbon-finance-ante-finance-medium</link>
            <guid>Briuk3BdpRI6bWISCDNe</guid>
            <pubDate>Thu, 31 Mar 2022 07:19:54 GMT</pubDate>
            <description><![CDATA[This post is intended to be a technical overview of the Ribbon Ante Tests and their mechanics.BackgroundRibbon is a DeFi protocol that helps users access DeFi structured products. Their Theta Vault product offers yield through an automated options strategy (the main V2 products at the moment automate weekly covered call strategies). Ante hosts real-time incentivized on-chain smart contract tests (”Ante Tests”) that pay out when code fails. This aligns teams and users and makes code trust expl...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1c7d9dbd0538550e296e7848bb60da53bda241da61aee6b1ed63914054cc57b5.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>This post is intended to be a technical overview of the Ribbon Ante Tests and their mechanics.</p><h2 id="h-background" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Background</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.ribbon.finance/"><strong>Ribbon</strong></a> is a DeFi protocol that helps users access DeFi structured products. Their Theta Vault product offers yield through an automated options strategy (the main V2 products at the moment automate weekly covered call strategies).</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.ante.finance/"><strong>Ante</strong></a> hosts real-time incentivized on-chain smart contract tests (”Ante Tests”) that pay out when code fails. This aligns teams and users and makes code trust explicit, resulting in a safer, more composable Web3 ecosystem. Responsible protocol teams can explicitly put “skin in the game” by staking their Ante Tests (which anyone can also challenge or stake), boosting their “<strong>Decentralized Trust Score</strong>”. In turn, developers can reference Ante trust scores to build more safely on top of protocols, and users can more clearly see community trust in protocols real-time.</p><h2 id="h-ribbon-tvl-plunge-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Ribbon TVL Plunge Test</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/main/contracts/ribbon/AnteRibbonV2ThetaVaultPlungeTest.sol">Code</a>; <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xc7b9768AFa59D4CF820C9f6479fAF0b916c18B9d">Live test</a></p><p><strong>AnteRibbonV2ThetaVaultPlungeTest</strong> checks that the TVL for any tested Ribbon V2 Theta Vault doesn’t fall by 90% from the time the test is deployed. While TVL is an imperfect metric for overall protocol success, it is a useful proxy for any number of catastrophic scenarios such as:</p><ul><li><p>Ribbon usage has declined precipitously</p></li><li><p>Ribbon funds have been drained by a hack/exploit</p></li></ul><p>Basically, if the TVL in the Ribbon V2 Theta Vaults has plunged over 90%, something catastrophic has likely befallen Ribbon.</p><h2 id="h-how-it-works" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How it works</h2><p>The test checks the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x25751853Eab4D0eB3652B5eB6ecB102A2789644B">ETH Covered Call V2</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x65a833afDc250D9d38f8CD9bC2B1E3132dB13B2F">WBTC Covered Call V2</a> Theta Vaults. Upon instantiating the Ante Test, the test iterates through the list of vaults and calculates the precise failure threshold for each vault by multiplying the current balance by the drop threshold — 10%.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f2e6e74cd8ef862478f95d4e09bd2e04986b11036ad26681b86d5d148ab84062.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AnteRibbonV2ThetaVaultPlungeTest.sol, lines 38–44</p><p>When <code>checkTestPasses()</code> is called by a challenger, the test iterates through the same set of vaults and compares each vault’s balance to its corresponding failure threshold. If any of the vaults’ TVL is below its threshold, then the entire Ante Test fails and challengers can claim funds.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/55b7ab62ec501fd507cef44c5cb1ab7c168a2123f281d0b032fcbd312802776f.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AnteRibbonV2ThetaVaultPlungeTest.sol, lines 65–73</p><p>Let’s take a closer look at how vault balances are calculated in the <code>calculateAssetBalance()</code> helper function. The underlying tokens controlled by the vault are split between two main contracts through the vault lifecycle:</p><ul><li><p>Opyn <em>MarginPool</em> contract when underlying has been used to mint call options</p></li><li><p>Ribbon vault contract in basically any other situation: if Ribbon users deposit mid-cycle; if all the options don’t sell out that week; if its auction profits; if users have queued for withdrawal but not withdrawn yet; if options have been settled for the week and not yet used to mint next week’s options</p></li></ul><p>The sum of these two balances represent the total current asset balance “in” a Ribbon vault (technically, tokens could also be held very briefly in the EasyAuction contract after people buy options but it is promptly transferred back to the Ribbon vault).</p><blockquote><p>Note that we also assume that there is only one type of collateral asset in a Theta Vault. This is currently true for the two vaults tested by this Ante Test, but as the contracts are upgradeable we can’t guarantee this will always be the case.</p></blockquote><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3045c39d4c64d0ace76ef712910414bd682237574cb89a13a7118dcb5c91afba.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AnteRibbonV2ThetaVaultPlungeTest.sol, lines 49–60</p><p>The reason we don’t just use Ribbon’s <code>totalBalance()</code> function and roll our own calculation logic in an independent <code>calculateAssetBalance()</code> function is because we can increase the surface area of potential vulnerabilities covered.</p><p>If we were to use the internal Ribbon state to calculate balance, since the contracts are upgradeable, there is a potential situation where an attacker could seize upgrade permissions then replace the contract with a malicious one that steals the funds but doesn’t change <code>vaultState.lockedAmount</code>. Another possible attack vector could be a bug in the RibbonV2 Theta Vaults which allows an attacker to steal funds but leaves <code>vaultState.lockedAmount</code> unchanged. In either of these cases, an Ante Test checking Ribbon’s internal state variables for balance could show the test still passing even though funds were no longer SAFU.</p><blockquote><p>As a general principle, writing test logic that doesn’t depend strongly on the tested contract’s own internal state helps make the test more robust against false negatives.</p></blockquote><h2 id="h-ribbon-multisig-token-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Ribbon Multisig Token Test</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/main/contracts/ribbon/AnteRibbonMultisigRBNTest.sol">Code</a>; <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0x64408eF5356f229b3E007370A3aB099cf63e5F18">Live test</a></p><p><strong>AnteRibbonMultisigRBNTest</strong> checks that the Ribbon multisig wallet always holds at least 1 million $RBN. Failure would indicate a catastrophic scenario with a &gt;99% drop in RBN balance (currently ~140M), which could mean that the multisig had been hacked or the team had rugged.</p><h2 id="h-how-it-works" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How it works</h2><p>The failure threshold is set in the constructor of the test:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a7226752d820e457353921834f33e73be0979e2678a2b35056c87b983c30ba22.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AnteRibbonMultisigRBNTest.sol, lines 27–32</p><p>The balance check is super straightforward: as long as the Ribbon multisig address still holds 1M or greater of $RBN, the test passes.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7158a3ab2ee030ab66d1e7c8ba266c45736d2aa1003a69363f868ba5e5d1966c.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AnteRibbonMultisigRBNTest.sol, lines 36–38</p><p>Pretty simple, right? But these are often the kind of fundamental assumptions that we want to make sure hold true for a protocol.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>We all know DeFi can be a dangerous place. Smart contracts can be opaque to your average DeFi user, and bad actors abound. Ante helps make code risk explicit, helping you make informed decisions about which protocols you use. Staking their tests could show a core team’s alignment with the community and their commitment to responsible code security. It’s a hard-to-fake signal of confidence in their code (literally skin in the game).</p><p>If you would like to learn more about how Ante could be useful for your protocol team, please reach out to us at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://signup.ante.xyz/">signup.ante.xyz</a>, read the docs at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://docs.ante.finance/">docs.ante.finance</a>, or follow the team on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a> and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.gg/ante">Discord</a> for more web3 security discussions!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante v0.5 Code Tour - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-v0-5-code-tour-ante-finance-medium</link>
            <guid>kOrZnTgmwGOCGHZApc0G</guid>
            <pubDate>Mon, 28 Mar 2022 11:13:31 GMT</pubDate>
            <description><![CDATA[This article is meant to give a technical overview of the Ante v0.5 codebase for developers — how it works, why we decided to do things the way we did, and the implications of those decisions (an internal audit of sorts). If that sounds interesting to you, then read on ~fren~. If you are unfamiliar with Ante and what it does, we recommend checking out our short intro here before reading this article.OverviewAnte v0.5 is a fairly simple system composed of three files: AnteTest.sol: This file c...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d19bcbe3eb2d69bd19fd70635e243b6a2f45bae2287b87368141875c7fa4fa6b.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>This article is meant to give a technical overview of the Ante v0.5 codebase <strong>for developers</strong> — how it works, why we decided to do things the way we did, and the implications of those decisions (an internal audit of sorts). If that sounds interesting to you, then read on ~fren~.</p><p>If you are unfamiliar with Ante and what it does, we recommend checking out <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.ante.finance/antev05/how-ante-works">our short intro here</a> before reading this article.</p><h2 id="h-overview" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Overview</strong></h2><p>Ante v0.5 is a fairly simple system composed of three files:</p><p><strong>AnteTest.sol:</strong> This file contains the abstract contract <code>AnteTest</code>, which both inherits the <code>IAnteTest</code> interface and is itself inherited by all <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests">Ante Tests written by our community</a>.</p><p><strong>AntePool.sol:</strong> This file contains the <code>AntePool</code> contract. Each Ante Pool is linked to a single Ante Test and enables individuals to stake and challenge that test’s invariant.</p><p><strong>AntePoolFactory.sol:</strong> This file contains the <code>AntePoolFactory</code> contract which enables the deployment of Ante Pools on-chain.</p><blockquote><p>These contracts can be viewed in <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/tree/v0.5/contracts">https://github.com/antefinance/ante-v0-core/tree/v0.5/contracts</a> and this code tour specifically references commit hash <code>5d7488e3dd7946a384f24b13f6a475b3ad709451</code>.</p></blockquote><p>Now let’s examine these three contracts in detail.</p><h2 id="h-antetestsol" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>AnteTest.sol</strong></h2><p>The interface <code>IAnteTest</code> defines 5 functions which are partially implemented by the abstract contract <code>AnteTest</code>.</p><p>The view functions in <code>IAnteTest</code> are implemented via the public variables <code>testAuthor</code>, <code>testName</code>, <code>protocolName</code>, and <code>testedContracts</code>. The <code>checkTestPasses</code> function is left unimplemented and must be implemented by any inheriting Ante Test.</p><blockquote><p>Note that <code>checkTestPasses</code> is defined as an <code>external</code> function but NOT as a <code>view</code>. Though inheriting Ante Tests can implement this function as a view function if they choose, it is not necessary and ultimately determined by whether testing the invariant requires mutating state or not.</p></blockquote><p><code>AnteTest</code> also includes the convenience method <code>getTestedContracts</code> which returns the entire <code>testedContracts</code> array, since the default generated getter only returns specific elements given an index.</p><p><code>AnteTest</code> is designed to be easy to inherit from, only requiring the inheriting contract to specify the name of the test for its own constructor. It also conveniently sets <code>testName</code> and <code>testAuthor</code>, but does <strong>not</strong> set <code>protocolName</code> and <code>testedContracts</code>, both of which must be initialized by the inheriting contract (usually in that contract’s constructor).</p><h2 id="h-antepoolfactorysol" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>AntePoolFactory.sol</strong></h2><p><code>AntePoolFactory</code> functions similarly to <code>UniswapV2Factory</code> in that it allows easy and standardized deployment of Ante Pools on chain. The key method here is <code>createPool</code>, which creates an Ante Pool given an Ante Test address. This method also makes sure that a pool hasn’t been created by this factory for the provided Ante Test yet and, <strong>importantly</strong>, initializes the created Ante Pool. This ensures that the Ante Pool is properly configured and performs several important validations on the Ante Test (described in the <strong>AntePool.sol</strong> section).</p><p>Another important function of <code>AntePoolFactory</code> is to store all of its own created Ante Pools. This mitigates a potential attack vector in which a hacker deploys a malicious Ante Pool and then steals staker and challenger funds. The pool address in this case can be checked against <code>allPools</code> in the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0xa03492A9A663F04c51684A3c172FC9c4D7E02eDc">official on-chain </a><code>AntePoolFactory</code>. If it’s not present, then the pool hasn’t been created by the factory and caution is warranted.</p><h2 id="h-antepoolsol" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>AntePool.sol</strong></h2><p>The <code>AntePool</code> contract is by far the most complex smart contract in our codebase, governing the interaction of stakers and challengers and ensuring that all stakeholders are properly rewarded depending on the current state of the underlying ante test.</p><p><strong>Initialization</strong></p><p>Initialization of the Ante Pool occurs in two steps. First, in the constructor, the <code>factory</code> variable is set to <code>msg.sender</code>. This is important because only the <code>factory</code> may call <code>initialize</code> to finish initializing the Ante Pool. Some other variables are also set in the constructor to their initial value, but it is not strictly important that they be initialized here vs in <code>initialize</code> or during definition.</p><p>The <code>initialize</code> function takes in an Ante Test address and configures the Ante Pool accordingly. Importantly, this function can only be called once to avoid malicious re-initialization of the contract, as enforced using the <code>notInitialized</code> modifier. This function also performs several important safety checks on the Ante Test, namely that it implements the <code>checkTestPasses</code> function and that this function currently returns <code>true</code>. Astute code readers may notice that <code>pendingFailure</code> (the variable which records whether or not the underlying Ante Test has failed) <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/41212a6c1d9b951ce0c6fea6f3a0819e58850e15/contracts/AntePool.sol#L85">is initially defined as </a><code>true</code> and only set to <code>false</code> in the <code>initialize</code> method. The reason for this is to avoid introducing a redundant modifier preventing all external functions in the Ante Pool contract from being called pre-initialization (a situation which also would never occur “naturally”). Instead, we can set <code>pendingFailure</code> to <code>true</code> initially and use the existing <code>testNotFailed</code> modifier to accomplish the same goal and seal off an unlikely edge case without wasting gas.</p><p>In practice, this two-step initialization is taken care of by the pool factory’s <code>createPool</code> function. This is also the reason why the process is split into two steps — since constructor arguments modify smart contract bytecode, having the initialization of the Ante Pool occur solely in the pool’s constructor would require a comparatively expensive on-chain byte manipulation step to place the Ante Test address in the Ante Pool’s bytecode in <code>createPool</code>.</p><p><strong>Decay</strong></p><p>During normal operation (i.e. while the underlying Ante Test still passes), challengers pay stakers a 20%/year fee called <em>decay</em>. This calculation is managed by the <code>updateDecay</code> function.</p><p>Since historical state data is not normally available on-chain, all the state required to compute the decay must be present on-chain at the time of the calculation. To accomplish this, we implement a common pattern in which the decay accrued is updated whenever a contract interaction occurs which may change the decay calculation.</p><p>Namely, <code>updateDecay</code> is called during <code>stake</code>, <code>unstake</code>, <code>unstakeAll</code>, and finally upon test failure in <code>checkTest</code>.</p><p>Interestingly, due to issues with approximating floating point calculations with integer arithmetic, small numerical errors in accrued decay accumulate over the course of normal pool operation. We investigated these numerical errors heavily and proved, both empirically and analytically, that they remain vanishingly small relative to pool balance changes and are extremely unlikely to result in material differences in staker and challenger payouts. The more quantitatively inclined readers may be interested in our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/uI_xvRFEuAFPjJpuuurM1x17b0A8z6up4gpFGL06Xcc">two-part</a> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/Af6k9RZMf81DyUiBtRoKb_PWYm4x24BRwq3vt0VSmxE">writeup</a> on this subject.</p><p><strong>Staking/Challenging</strong></p><p>At the code level, staking and challenging work similarly. Both use the <code>stake</code> method, with the <code>msg.value</code> of the transaction indicating how much value is being deposited and a single boolean flag <code>isChallenger</code> determining whether the user is staking or challenging.</p><p>The data structures used to store staker and challenger info, <code>stakingInfo</code> and <code>challengerInfo</code> respectively, are both instances of the <code>PoolSideInfo</code> struct. This struct also tracks how much each user balance has changed due to decay.</p><p>There are slight differences in the deposit and withdraw workflows between stakers and challengers to mitigate bad behavior. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/41212a6c1d9b951ce0c6fea6f3a0819e58850e15/contracts/AntePool.sol#L188">Challengers are required to deposit at least 0.01 ETH</a>, in order to mitigate an attack whereby a user can challenge every pool and front-run a <code>checkTest</code> call which causes the underlying ante test to fail (this is discussed in greater detail below). <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/41212a6c1d9b951ce0c6fea6f3a0819e58850e15/contracts/AntePool.sol#L251">Stakers must wait at least 24 hours to withdraw</a>, to avoid a situation in which stakers are given advance warning of an exploit and can withdraw before challengers can trigger a failing test and claim their reward. The data tracking when stakers are allowed to withdraw is stored in <code>withdrawInfo</code>.</p><p><strong>Check Test and Claim</strong></p><p>Challengers can check if the underlying Ante Test linked to an Ante Pool is failing or not by calling the pool’s <code>checkTest</code> function. In order to properly incentivize active checking of Ante Tests, we include a <code>VERIFIER_BOUNTY</code> of 5% of staker capital, paid to the challenger who successfully triggers a failing test.</p><p>To avoid arbitrary addresses being able to front-run a <code>checkTest</code> transaction, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/41212a6c1d9b951ce0c6fea6f3a0819e58850e15/contracts/AntePool.sol#L293">we restrict the set of eligible verifiers to existing challengers who have been challenging for at least 12 blocks</a>. Additionally, to prevent arbitrary addresses from challenging a failing Ante Test after observing the corresponding <code>checkTest</code> transaction in the mempool, we restrict the set of challengers eligible for any payout to those who have challenged for at least 12 blocks. Both these checks are enabled via the<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/41212a6c1d9b951ce0c6fea6f3a0819e58850e15/contracts/AntePool.sol#L131"> </a><code>eligibilityInfo</code><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/41212a6c1d9b951ce0c6fea6f3a0819e58850e15/contracts/AntePool.sol#L131"> struct</a>.</p><p>However, we acknowledge that these solutions don’t perfectly solve the front-running issue, and are actively working on more robust mechanisms.</p><p>Note that since the total eligible challenger balance (using the above criteria) is recalculated upon <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/41212a6c1d9b951ce0c6fea6f3a0819e58850e15/contracts/AntePool.sol#L308">test failure</a>, small numerical errors accumulated prior to test failure do not prevent challengers from claiming their full share of the staked balance.</p><p>As challengers <code>claim</code> their corresponding share of rewards following test failure, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/41212a6c1d9b951ce0c6fea6f3a0819e58850e15/contracts/AntePool.sol#L327">their balance is set to zero</a> so they cannot erroneously claim multiple times.</p><h2 id="h-security-considerations" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Security Considerations</strong></h2><p>Writing bug-free code is hard, but there are tools available to Solidity developers which make it a bit easier. It’s extremely important to make use of methods like audits, bug bounties, insurance, unit testing, static analysis, input fuzzing, formal verification, and other emerging tools (like Ante Tests) to guarantee the safety of user funds to the maximal extent possible.</p><p>Though it by no means guarantees absolute code safety, we are proud of the unit testing suite we developed for Ante v0.5. But don’t just take our word for it — you can run the tests yourself from our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/">public repo</a>. These tests fall broadly into three categories:</p><ul><li><p>Tests of initial conditions</p></li><li><p>Tests of final state after a transition (i.e, a user stakes, or calls <code>checkTest</code>, challengers can claim correct amount after test failure, etc.)</p></li><li><p>Tests of specific exploits or disallowed behavior (i.e., Ante Pool can’t be initialized twice, stakers can’t withdraw after test failure, etc.)</p></li></ul><p>You can see these patterns in action in our testing suite, as shown below in our tests on the reward claim functionality:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2c3fb48362e27cfd8782c23ff0b1ba22b83eb48859a2e4c44085ed88e0708406.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>We also include the output of running slither, a popular static analyzer, on our repo for convenience <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/v0.5/slither/slither_5d7488e3dd7946a384f24b13f6a475b3ad709451.txt">here</a>.</p><p>We hope you enjoyed this in-depth discussion of the Ante v0.5 codebase and the “peek behind the curtain” into some of the considerations underpinning the protocol design. If you have any questions or just want to discuss further, feel free to message us on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/antefinance">Twitter</a> or connect with us in our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.gg/ante">Discord</a>!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante Tech Talk #4: Fixed-point Arithmetic and Rounding in AntePool (cont’d)]]></title>
            <link>https://paragraph.com/@ante-finance/ante-tech-talk-4-fixed-point-arithmetic-and-rounding-in-antepool-cont-d</link>
            <guid>tFVQFkw3XYT7W5AE43xM</guid>
            <pubDate>Mon, 28 Mar 2022 11:12:20 GMT</pubDate>
            <description><![CDATA[This continues a multi-part series walking through the Ante v0.5 protocol design as well as basic secure smart contract development practices. Check out Part 1, Part 2, and Part 3. Recall from Part 3 that we want to ensureis always non-negative and does not grow too large. Our initial fuzz testing results below showed this excess balance (in blue) appears to grow quite slowly over time. Today’s post will explain how we obtained provable bounds (in orange) on the excess balance. As before, we ...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/07bc2d1a396ec7c9146a3d23b406e5eea5b22f43cdd7ac748268c9c5fe49bdd1.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><em>This continues a multi-part series walking through the Ante v0.5 protocol design as well as basic secure smart contract development practices. Check out </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/B7IVJfO61qi_mhSjlaUuPSfnotx1kir-IzMjLEi3n0g"><em>Part 1</em></a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/zFeUr2OO8pcbgHOzxamkbQNvMUTR5ETKHJ2DrKNAKik"><em>Part 2</em></a>, and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/uI_xvRFEuAFPjJpuuurM1x17b0A8z6up4gpFGL06Xcc"><em>Part 3</em></a>.</p><p>Recall from <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/uI_xvRFEuAFPjJpuuurM1x17b0A8z6up4gpFGL06Xcc">Part 3</a> that we want to ensure</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5cf118c933f48f5a7966180c492e55bedda2cd6fdce96e9905d8bc41b05aa8cb.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>is always non-negative and does not grow too large. Our initial fuzz testing results below showed this excess balance (in blue) appears to grow quite slowly over time. Today’s post will explain how we obtained provable bounds (in orange) on the excess balance. As before, we will focus on the Challenger excess balance.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1743b569edbac39415b0078a25e815cb56984c22feaf6391c31cc10b45c68ff8.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Excess balances accrued over time in a single run of our fuzz test</p><h2 id="h-characterizing-and-bounding-the-excess-balance" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Characterizing and bounding the excess balance</h2><p>To analyze the challenger excess balance, we first list all state variables which determine the total challenger balance and each user’s balance:</p><ul><li><p><code>challengerInfo.totalAmount</code>(denominated in wei)</p></li><li><p><code>challengerInfo.decayMultiplier</code></p></li><li><p><code>challengerInfo.userInfo[addr].startAmount</code>(denominated in wei)</p></li><li><p><code>challengerInfo.userInfo[addr].startDecayMultiplier</code></p></li></ul><p>We then determine all functions in <code>AntePool</code> which modify these variables. We find that all modifications occur through the following operations:</p><ul><li><p><code>stake()</code></p></li><li><p><code>unstake()</code></p></li><li><p><code>updateDecay()</code>,</p></li></ul><p>where we note that several other functions modify these variables only via <code>updateDecay()</code>.</p><p>Our analysis (full analysis <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ante.finance/s/decay.pdf">here</a>) shows that the challenger excess balance is always non-negative and bounded above by the number of calls to these functions. More precisely, we find that</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ef58354c4237a4092604dbd73631140457e8e89e3ea3ab95c9943d32ec70b933.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>where <em>N_D</em> is the number of calls to <code>updateDecay()</code>, <em>N_S</em> is the number of calls to <code>stake()</code>, <em>N_U</em> is the number of calls to <code>unstake()</code>, and the total amount staked (in wei) is bounded by <em>M</em>·<code>challengerInfo.decayMultiplier</code> at all times.</p><p>Remember the challenger excess balance is denominated in wei, so our bound on challenger excess balance is extremely small for reasonable values of parameters. Concretely, if there are 10,000 challengers, each of which calls <code>stake()</code>or <code>unstake()</code> 100 times, <code>updateDecay()</code>is called every minute for 10 years, and the total value in the challenger pool is at most 25M ETH, then this bound would come to 0.0015 ETH.</p><h2 id="h-proving-the-bound" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Proving the bound</h2><p>Our full proof of the bound is written up <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ante.finance/s/decay.pdf">here</a>, but we give a flavor of our analysis in this post. Assuming that an Ante Pool is in a state where the bounds hold, we will show that after applying any of the operations <code>stake()</code>, <code>unstake()</code>, and <code>updateDecay()</code> the bounds still hold. When an AntePool is started, the challenger excess balance is 0, so this would imply that the bounds hold at initialization. In this post, let’s see why the <code>updateDecay()</code> operation does not change the fact that challenger excess balance is non-negative.</p><p>Suppose that <em>T</em> blocks have passed since the last call to <code>updateDecay()</code>, either directly or through another external function call. The effect of <code>updateDecay()</code> is then to update the challenger state variables as follows:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7438fdabd06a01e925858e90e372a5147742dfe8ffe22afede55186dc15130ed.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Updates to challengerInfo state variables after updateDecay()</p><p>where we use <em>totalAmount</em>′ and <em>decayMultiplier</em>′ to denote the state after the <code>updateDecay()</code> call.</p><p>At this point, the unrounded challenger balance for address <code>addr</code> becomes:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c768c218e92391b7f90301e7f3c0c4aba284f753bde839c74b73693b19c9062a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The bound in the last line works because ⌊decayMultiplier⌋ ≤ decayMultiplier</p><p>If we sum this balance over all challenger addresses then we obtain:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c017d82c86de187c4b97e2f5e46df99db5807471e11a4d920c30785e055c0f1f.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>which shows the challenger excess balance remains non-negative as we hoped!</p><p>Of course, we’d like to ensure that <code>updateDecay()</code> still preserves the upper bound, that other operations still preserve both bounds, and that a similar analysis also applies to the Staker side. We invite any interested Ante frens to check out our more formal analysis <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ante.finance/s/decay.pdf">here</a>.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>To try out Ante for yourself, stake or challenge Ante Tests on Ante v0.5 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://app.ante.finance/"><strong>live</strong></a> on Mainnet now. If you’d like to get more involved, you can now write your own Ante Tests or ask your favorite protocols to write and stake their own Ante Tests!</p><p>Let us know if you have any questions/comments, follow @AnteFinance on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a>, and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://discord.ante.finance/">Discord</a> for more discussion!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante Code Tour: Ribbon Finance - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-code-tour-ribbon-finance-ante-finance-medium</link>
            <guid>TnbsCnIA9GArdPF27GRA</guid>
            <pubDate>Wed, 23 Mar 2022 06:33:07 GMT</pubDate>
            <description><![CDATA[This code tour is intended to give technical or tech-adjacent people (who may be newer to Solidity or to DeFi) a casual walkthrough of the Ribbon V2 codebase so they can improve their familiarity with and understanding of Ribbon V2, with a focus on the core Solidity contracts. We’ve also added some thoughts on specific design choices and object interactions. We’re excited to tour the Ribbon V2 code base together!BackgroundRibbon is a decentralized finance (DeFi) protocol that creates algorith...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/70677581eed8b9d3e4ecfd23115270cdc2ef653eb74b3d54777284526df99040.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>This code tour is intended to give technical or tech-adjacent people (who may be newer to Solidity or to DeFi) a casual walkthrough of the Ribbon V2 codebase so they can improve their familiarity with and understanding of Ribbon V2, with a focus on the core <strong>Solidity</strong> contracts. We’ve also added some thoughts on specific design choices and object interactions.</p><p>We’re excited to tour the Ribbon V2 code base together!</p><h2 id="h-background" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Background</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.ribbon.finance/">Ribbon</a> is a decentralized finance (DeFi) protocol that creates <strong>algorithmic structured products</strong> for users to earn yield on digital assets. Their most popular structured products are <strong>vaults</strong> that automatically sell “covered call” options on ETH and wrapped Bitcoin (WBTC).</p><p>Ribbon works by hosting <strong>vaults</strong> that users can use to generate yield on their digital assets. The most popular V2 vaults generate yield by selling out-of-the-money options using Gnosis auctions.</p><h2 id="h-getting-started" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Getting Started</h2><p>One thing to note is that Ribbon’s code is <strong>very modular</strong> — modularity is great for future iterations and improvements (any module can be easily “swapped out” for another and tested in a relatively self-contained and logically easy-to-understand way). However, this <em>does</em> mean that reading through the code base can be quite daunting (due to the number of apparent “moving parts”).</p><p>While we’ve skimmed them, we haven’t studied <em>every</em> single file in all the folders listed in depth line-by-line, so this is intended more as a 10,000-meter “view” of RibbonV2.</p><blockquote><p><strong>Note:</strong> this walkthrough is <strong>NOT AN AUDIT</strong> and is meant for <strong>educational purposes only</strong>. Please do <strong>NOT</strong> take anything here as a security recommendation or an investment recommendation. Not financial advice. Comments are based on the 2022–02–03 commit <code>735f076376edef3230771efc32f81bbd2dcecda5</code> on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ribbon-finance/ribbon-v2/tree/master/contracts">ribbon-v2 master</a>.</p></blockquote><p><strong>Quick Tip:</strong> when browsing alongside us through the codebase, if you’re curious to see how <code>someRibbonFunction()</code> is used in the codebase, you can (if on a *nix machine):</p><ol><li><p>Open up your command line (Terminal in MacOS or just a CLI)</p></li><li><p>Clone the RibbonV2 GitHub repo to your local machine (e.g. <code>git clone https://github.com/ribbon-finance/ribbon-v2.git</code> )</p></li><li><p>Navigate to the <code>contracts</code> folder</p></li><li><p>Run <code>grep -R someRibbonFunction .</code> to see where else in the codebase <code>someRibbonFunction</code> pops up!</p></li></ol><h2 id="h-directory-structure" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Directory Structure</h2><p>There are a few folders in the <em>contracts</em> repo for Ribbon, but we’ll focus the more detailed part of the walkthrough on just a small number of files within the <em>libraries</em> and <em>vaults</em> folder, where most of the “body” of Ribbon sits.</p><h2 id="h-interfaces" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong><em>interfaces</em></strong></h2><p>For those new to Solidity, interfaces (typically denoted with an ‘I’ prefix) allow a developer to define how their code will interact with other pieces of code. When writing a smart contract that interacts with another smart contract, then, the simplest way to bring in those “rules of engagement” is by importing the interface.</p><p>Ribbon defines a number of interfaces here for purposes including interacting with external systems (e.g. <em>IGnosisAuction.sol</em>, <em>ISwapRouter.sol</em>) and dealing with specific tokens (<em>IWETH.sol</em>, <em>IERC20Detailed.sol</em>). Notably, <em>IRibbonThetaVault.sol</em> is the interface to access instances of Ribbon’s Theta Vault. This is used, for example, when the code to auction off options needs to access a given Theta Vault, or in Ribbon’s more complex Delta Vaults.</p><h2 id="h-libraries" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong><em>libraries</em></strong></h2><p>Lots of files here! It’s a good practice for any project to abstract repeated calculations into library functions or to grab those files from a trusted source. Here, in addition to libraries you’d expect for various helpers, there is also preliminary functionality for vaults (and their periodic behavior) sketched out in <em>Vault.sol</em> and <em>VaultLifecycle.sol</em>.</p><h2 id="h-storage" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong><em>storage</em></strong></h2><p>This directory contains the data structures used by various Ribbon vaults. These storage objects are written in a way that allows them to be upgraded alongside the Ribbon protocol and seamlessly reused across minor version releases without interrupting the end user experience. We go into a little more detail below.</p><h2 id="h-tests" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong><em>tests</em></strong></h2><p>This subdirectory contains scaffolding and mock data structures for off-chain tests.</p><h2 id="h-utils" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong><em>utils</em></strong></h2><p><em>utils</em> contains helper files (e.g. for selecting appropriate params) not referenced directly by other Solidity files in the <em>contracts</em> folder but used in TypeScript test scaffolding in the rest of the <em>ribbon-v2</em> repository.</p><h2 id="h-vaults" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong><em>vaults</em></strong></h2><p>This subdirectory hosts a lot of the core vault code (both the base classes that get inherited, as well as the implementations) of various vaults. Note that there are several vault types here that are not yet deployed on Mainnet, including a Delta Vault that can potentially buy the options produced by a Theta Vault.</p><h2 id="h-vendor" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong><em>vendor</em></strong></h2><p>Some custom code (including what appears to be a Ribbon-written proxy) for upgrading, including a math helper (used in some <em>libraries</em> code).</p><h2 id="h-theta-vault-design-and-walkthrough" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Theta Vault Design &amp; Walkthrough</h2><p>In this section we’ll go a little deeper into one of the key files that help define the Ribbon Theta Vaults!</p><p><strong>What is a Theta Vault?</strong></p><p>A Ribbon Theta Vault is a vault that generates yield by algorithmically selling options on the digital assets deposited via Gnosis auctions (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gnosis-auction.eth.link/#/docs#topAnchor">Learn more</a> about Gnosis Auctions)<strong>.</strong></p><h2 id="h-design-pattern-proxy-upgradeable-contracts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Design pattern: proxy upgradeable contracts</h2><p>Any highly innovative DeFi protocol like Ribbon faces the challenge of balancing shipping speed with security. It can be easier to rapidly innovate when you can push <strong>upgrades</strong> to an existing contract. However, upgradeability can introduce additional security risks if not managed properly.</p><p>Ribbon uses an upgradeable proxy pattern in order to allow for protocol upgrades — that is, it uses a proxy contract to point to the current “correct” implemented version of a smart contract. There are some implementation wrinkles with proxy upgradable contracts (e.g. upgradeable contracts cannot be initialized using constructors, but there are workarounds), but from a “vault security” standpoint, there are two things we wanted to point out in Ribbon V2 before the actual walkthrough: privileged roles and storage variables.</p><h2 id="h-privileged-roles" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Privileged roles</h2><p>Ribbon V2 has two important “<strong>trusted</strong>” roles: <em>Admin</em> and <em>Owner</em>. <em>Admins</em> can upgrade the proxies for Theta Vaults, and <em>Owners</em> can update vault parameters. Whenever privileged roles exist, the potential for an attack through those roles exists. A compromised multisig role could theoretically cause unforeseen problems!</p><p>The Ribbon team has stated they are moving toward greater decentralization (as seen already in the Ribbon V1 → V2 feature set), but it is currently an open-source system with both trusted (e.g. upgradeable proxy pattern) and trustless components.</p><blockquote><p>Note: there is a third role, <em>Keeper</em>, but it is used for operating vaults rather than upgrading code</p></blockquote><h2 id="h-storage-variables" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Storage variables</h2><p>Upgradeability means that additional functionality can be added to Ribbon Theta Vaults over time without requiring users to “exit and re-enter” the Ribbon system after major version updates. However, if there is important data saved in storage, <strong>it is important that the inheritance chain is carefully updated otherwise the data could be corrupted/lost.</strong></p><p>Due to the way storage works in Solidity, storage can only be safely appended to the end of the existing storage slots for a contract. In practice, this implies 3 main approaches to adding storage variables in upgradeable contracts:</p><ol><li><p>Add storage to the base contract only</p></li><li><p>Add storage to the final contract in the inheritance chain</p></li><li><p>Add “gaps” in the preceding inherited contracts just in case you need to fill these in with storage variables later on</p></li></ol><p>Ribbon (as well as Compound) uses the second method of updating storage variables by creating a new version of <code>RibbonThetaVaultStorage</code> in the inheritance chain whenever new storage variables are needed. These versions of the storage contract (using the naming convention of affixing V1, V2, V3, etc. after the class name) are then all inherited by the base contract (<code>abstract contract RibbonThetaVaultStorage is RibbonThetaVaultStorageV1, RibbonThetaVaultStorageV2, ...</code>).</p><p>Doing this inheritance properly means that “wonky” (yes, that’s a very rigorous and non-hand-wavy description) things don’t happen to data in storage and that the seamless transition of user data is maintained!</p><h2 id="h-vaultlifecyclesol-walkthrough" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">VaultLifecycle.sol walkthrough</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ribbon-finance/ribbon-v2/blob/master/contracts/libraries/VaultLifecycle.sol"><em>VaultLifecycle.sol</em></a> is a key library file that governs the interaction of Ribbon Vaults with all other contracts/protocols including:</p><ul><li><p><strong>Opyn</strong> — <em>MarginPool</em> contains all the collateral used for minting oTokens (options tokens), while <em>Controller</em> governs all interactions with MarginPool — any minting/redemption of oTokens goes through the Controller. This is called the <code>GAMMA_CONTROLLER</code> in ribbon’s Vault contracts.</p></li><li><p><strong><em>StrikeSelection</em></strong> — Ribbon’s contract which selects the next options strike price</p></li><li><p><strong>Gnosis</strong> — interacts with Gnosis <em>EasyAuction</em> protocol through Ribbon’s own <em>GnosisAuction.sol</em> smart contract. <em>GnosisAuction</em> also picks the option price premium by querying Ribbon’s <em>OptionsPremiumPricer</em> contract</p></li></ul><p>A couple interesting notes on interacting with Opyn:</p><ul><li><p>All controller actions sent to the Opyn <em>GammaController</em> are run through the <code>operate</code> method. This method runs an array of actions then checks whether or not the resulting vault state is valid with <code>_verifyFinalState</code></p></li><li><p>Interestingly enough, Opyn doesn’t publicize its v2 interface and the one available online (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://v2.opyn.co/">v2.opyn.co</a>) has no ability to create vaults</p></li></ul><p><strong>Notable functions in <em>VaultLifecycle</em>:</strong></p><ul><li><p>(Lines 47–99) the somewhat confusingly-named <code>commitAndClose</code> calculates the parameters of the next option (strike, premium, address, etc.) but does not actually close the current option. Instead, these parameters are passed to a function in the parent Vault contract — this parent function closes the existing option (by calling VaultLifecycle’s <code>settleShort</code> in the case of the Theta Vault)</p></li><li><p>(Lines 165–269) <code>rollover</code> is a view function that calculates the new Vault share price, vault fees, new collateral amount, pending withdraw amount based on existing vault state and rollover params. Called by <em>RibbonVault.sol</em>’s <code>_rollToNextOption</code></p></li><li><p>(Lines 279–371) <code>createShort</code> mints options based on the vault’s current locked balance. Called by parent Theta Vault’s <code>rollToNextOption</code> function which then subsequently starts a Gnosis auction for the minted options</p></li><li><p>(Lines 381–427) <code>settleShort</code> closes the current short and retrieves collateral from Opyn, called by parent Theta Vault’s <code>commitAndClose</code></p></li></ul><blockquote><p>Note: during our limited walkthrough, we could not find where the logic that enforces that <code>commitAndClose</code> can only be called after option expiry is located... it’s possible that something will revert somewhere if called before option expiry (likely in Controller). On the other hand, <code>rollToNextOption</code> in the Vault contract does require that the current block timestamp be greater than <code>optionState.nextOptionReadyAt</code> .</p></blockquote><h2 id="h-ribbonthetavaultsol-brief-walkthrough" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">RibbonThetaVault.sol brief walkthrough</h2><p>RibbonThetaVault.sol puts everything together and implements the unique logic for Theta Vaults.</p><ul><li><p>(Lines 1–17) Lots of imports! You’ll recognize some files mentioned earlier like <em>Vault.sol</em> and <em>VaultLifecycle.sol</em>.</p></li><li><p>(Lines 25–203) Defining events and data structures. Note the responsible warning for developers noting that all storage variable updates need to happen in <code>RibbonThetaVaultStorage</code> and that <code>RibbonThetaVault</code> should not inherit from any contracts aside from <code>RibbonVault</code> and <code>RibbonThetaVaultStorage</code> (recall our earlier discussion about storage variables in upgradable contracts)</p></li><li><p>Depending on usage by other contracts, the events could also be defined in a separate file and inherited by RibbonThetaVault</p></li><li><p>(Lines 205–291): Various parameter setters — note that <code>onlyOwner</code> and <code>onlyKeeper</code> modifiers are applied to various functions, meaning that not just <em>any</em> anon can set these params!</p></li><li><p>(Lines 292–494) Various vault operations. A few key things to note about the operations:</p></li><li><p>The <code>onlyKeeper</code> modifier is used to restrict access for some operations (e.g. <code>rollToNextOption()</code>) to only Keepers</p></li><li><p>Line 300 <code>function withdrawInstantly(uint256 amount)</code> is a good example of the Checks-Effects-Interactions (C-E-I) pattern used in practice! First, the requirements around a user’s deposits and balances are checked, followed by state variable changes, finally followed by transfer of value. Note the <code>nonReentrant</code> modifier is also used, presumably to reduce the attack surface area.</p></li></ul><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>We hope you’ve learned a bit about Ribbon and better understand some of the design decisions and workings of the protocol. If there’s anything you’d like us to dig more into with the Ribbon codebase, let us know in the comments!</p><h2 id="h-about-ante" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">About Ante</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.ante.finance/"><strong>Ante</strong></a> hosts real-time incentivized on-chain smart contract tests (”Ante Tests”) that pay out when code fails. This aligns teams and users and makes code trust explicit, resulting in a safer, more composable web3 ecosystem. Responsible teams like Ribbon🎀 can explicitly put “skin in the game” by staking their Ante Tests (which anyone can also challenge or stake), boosting Ribbon’s “<strong>Decentralized Trust Score</strong>”. In turn, developers can reference Ante trust scores to build more safely on top of Ribbon, and users can more clearly see community trust in Ribbon real-time.</p><p>If you would like to learn more about how Ante could be useful for your protocol team, please reach out to us at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://signup.ante.xyz/">signup.ante.xyz</a>, or follow the team on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a> and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.gg/ante">Discord</a> for more web3 security discussion!</p><h2 id="h-reference-links" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Reference Links</h2><p>Documentation: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.ribbon.finance/developers/ribbon-v2">https://docs.ribbon.finance/developers/ribbon-v2</a></p><p>GitHub: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ribbon-finance/ribbon-v2">https://github.com/ribbon-finance/ribbon-v2</a></p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Pendle x Ante: Pendle Ante Tests Explained - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/pendle-x-ante-pendle-ante-tests-explained-ante-finance-medium</link>
            <guid>hGQCGUc6x1muxXfxDCUt</guid>
            <pubDate>Wed, 09 Mar 2022 13:00:57 GMT</pubDate>
            <description><![CDATA[Hello Pendlefrens and Anteans! As you may have heard, as of today Pendle has deployed and staked 6 different Ante Tests for the Pendle protocol. We’re all excited about our partnership and what it means for the future of decentralized trust in Web3. For those who may be wondering how the Pendle Ante Tests work, this post is intended to be a quick overview of the tests and their mechanics.BackgroundPendle allows users to deposit a yield-bearing token (e.g. the SushiSwap USDC/ETH LP) and split ...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cae6f527babccf9dca4ae3115ea03405ab3e338212228a7354d6a2b51a2b6813.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Hello Pendlefrens and Anteans! As you may have heard, as of today Pendle has deployed and staked 6 different Ante Tests for the Pendle protocol. We’re all excited about our partnership and what it means for the future of decentralized trust in Web3. For those who may be wondering how the Pendle Ante Tests work, this post is intended to be a quick overview of the tests and their mechanics.</p><h2 id="h-background" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Background</h2><p><strong>Pendle</strong> allows users to deposit a yield-bearing token (e.g. the SushiSwap USDC/ETH LP) and split it into an ownership token (<strong>OT</strong>) and future yield token (<strong>YT</strong>) representing the principal and future yield components of the underlying asset value over a given period of time. The yield tokens can be purchased, sold, traded, or staked in various liquidity pools in order to earn incentives, and yield is distributed to holders of the YT until expiry.</p><p><strong>Ante</strong> is a trust protocol that enables <strong>Ante Tests: Smart Tests for Smart Contracts</strong> that programmatically check and provide financial guarantees around a protocol’s key assumptions in real time. Responsible project teams like Pendle explicitly put “skin in the game” by staking crypto behind their Ante Tests (which anyone can also challenge or stake) to boost Pendle’s “<strong>Decentralized Trust Score</strong>” (check it out <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/protocol/Pendle">here</a>). In turn, developers can reference Ante to build more safely on top of Pendle, and users can more explicitly see community trust in Pendle real-time.</p><h2 id="h-overall-test-architecture" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Overall Test Architecture</h2><p><em>In case you want to follow along, we are looking at </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/tree/main/contracts/pendle"><em>ante-community-tests/contracts/pendle</em></a><em>, commit </em><code>14ce1a83fca96eabb10bed0dde02db55dcb499ae</code><em> on 2022-03-09.</em></p><p>Four of the Ante Tests cover Pendle’s forge contracts, which govern the critical process of splitting underlying yield tokens into their OT and YT components. The remaining two tests cover Pendle’s markets. Each of the six Pendle Ante Tests has its own Ante Pool. As the tests and pools are composable, in the future, one could potentially write a “wrapper” Ante Test/Pool that would act as a test aggregator for Pendle’s tests.</p><h2 id="h-pendle-aave-forge-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Pendle Aave Forge Test</h2><p>(<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/38246ab9dc6b1fc51e203c33556b44851e42d4fb/contracts/pendle/AntePendleAaveForgeTest.sol">Code</a>; <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xeAe27AfaCB56618e1627e10924D66fc5b0A00C3a">Live test</a>)</p><p>This is a pretty straightforward test that checks whether the Pendle yield token holder address owns enough aUSDC to exchange 1:1 for all aUSDC OTs, i.e. the forge never mints more OTs than can be redeemed. If Pendle is ever unable to pay out redeemed OTs, that means the protocol is insolvent, so this is a critical invariant to check!</p><p>As written, the test checks this condition for the current aUSDC OT (expiring 2022–12–29) and fails if it does not meet this condition.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/66de56c00923d54ee11a49d4e0f09eb565d4a1eec2f71931d2869f22c2ff8885.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AntePendleAaveForgeTest.sol, lines 39–41</p><p>Note that the test implements a 1% margin of error to account for any very minor precision issues that could arise.</p><p>Note that the OT contract that this Ante Test checks is fixed, meaning that at some point if a new aUSDC OT contract were to be deployed (e.g. for 2023 expiry), this Ante Test would not automatically check that contract. In order to check any new OT contracts, a new version of this Ante Test would need to be deployed and liquidity potentially migrated over to the new test.</p><blockquote><p><strong>A note on test “updatability”:</strong> When writing tests that iterate over a set of contracts that may update or expire over time, it can <em>sometimes</em> be beneficial to add functions within the test to allow the addition of additional contracts, or to reference a list of contracts held by another contract that can be updated when new contracts are added. This must be balanced with the increased attack surface area this creates for the test itself; if relying on a privileged role to update contracts, this could be seen as reducing decentralization and potentially allows a malicious protocol team to prevent a test from failing, while allowing anyone to add a contract (even with checks to make sure a valid OT contract is added) could potentially be exploited by providing a malicious contract to the test. Philosophically speaking, it could be seen as unfair for a test to change tested contracts after people have already made the decision to stake/challenge the test, even if they can withdraw their capital. In light of these considerations, the Pendle and Ante teams decided not to implement the ability to add additional contracts in any of the Pendle Ante Tests covered in this post.</p></blockquote><h2 id="h-pendle-sushi-pep-forge-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Pendle Sushi PEP Forge Test</h2><p>(<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/38246ab9dc6b1fc51e203c33556b44851e42d4fb/contracts/pendle/AntePendleSushiPEPForgeTest.sol">Code</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0x8417a4cD3490265cFb9d63bD9A2bE8c760A40fA6">Live test</a>)</p><p>This is similar in structure to the <strong>Pendle Aave Forge Test</strong>, with additional complexity due to the fact that we are dealing with LP tokens so we need to calculate an exchange rate for redemption.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b974026f60253e2ec16ef6ba563526b093ae2187ef37afbfa58f32004ddb80ea.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AntePendleSushiPEPForgeTest.sol, lines 43–53</p><p>In this case, the exchange rate is determined using the following equation:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8a013baf6d0b030c5bdb222a83f2aa33b2e1fe25c3636bb0095f782fde3c9c58.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>which is then used to compare the supply of OT against LP. Note that the test implements a 1% margin of error to account for minor fluctuations in exchange rate that can occur when more LPs are minted for the fee.</p><h2 id="h-pendle-sushi-ethusdc-forge-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Pendle Sushi ETHUSDC Forge Test</h2><p>(<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/38246ab9dc6b1fc51e203c33556b44851e42d4fb/contracts/pendle/AntePendleSushiETHUSDCForgeTest.sol">Code</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0x737eD79cC9867E9Ab57Ec8DCf83c322537350787">Live test</a>)</p><p>Similar to the <strong>Pendle Sushi PEP Forge Test</strong>, this checks that the yield token holder holds enough underlying token to cover OT redemption.</p><p>The only difference here is that the LP balance must be pulled through MasterChef (ETH/USDC is an incentivized pool on SushiSwap so the yield token holder needs to stake to MasterChef in order to get rewards).</p><pre data-type="codeBlock" text="// Getting LP balance for PENDLE/ETH LP
uint256 lpBal = IERC20(yieldToken).balanceOf(yieldTokenHolder);// Getting LP balance for ETH/USDC LP
uint256 lpBal = IMasterChef(masterChef).userInfo(pid, yieldTokenHolder).amount;
"><code><span class="hljs-comment">// Getting LP balance for PENDLE/ETH LP</span>
<span class="hljs-keyword">uint256</span> lpBal <span class="hljs-operator">=</span> IERC20(yieldToken).balanceOf(yieldTokenHolder);<span class="hljs-comment">// Getting LP balance for ETH/USDC LP</span>
<span class="hljs-keyword">uint256</span> lpBal <span class="hljs-operator">=</span> IMasterChef(masterChef).userInfo(pid, yieldTokenHolder).amount;
</code></pre><h2 id="h-pendle-compound-forge-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Pendle Compound Forge Test</h2><p>(<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/38246ab9dc6b1fc51e203c33556b44851e42d4fb/contracts/pendle/AntePendleCompoundForgeTest.sol">Code</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0x36CC04E78F698457432b8e833FfF8F38C46E54F1">Live test</a>)</p><p>This test covers the solvency of the Compound cDAI forge — with this, the 4 non-expired major Pendle markets on Ethereum are tested for solvency. Talk about covering your bases! 💪</p><p>One thing we’re excited about with this test is that it represents the first live Ante Test that doesn’t only use external view functions to check whether the test passes. This has always been an intended capability of the Ante Test design — testing certain failure conditions may require some manipulation of state outside the Ante Test — but the tests to date had not required it.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1dbb95d32205bed69825ced7a413846be814b649e415578d04b388f1236cc179.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AntePendleCompoundForgeTest.sol, lines 49–53</p><p>In this case, the <code>exchangeRateCurrent()</code> function updates the accrued interest when called, which can result in a state change.</p><h2 id="h-pendle-market-weight-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Pendle Market Weight Test</h2><p>(<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/38246ab9dc6b1fc51e203c33556b44851e42d4fb/contracts/pendle/AntePendleMarketWeightTest.sol">Code</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xD175Ec2e11FF2Ece50848b5488fc4DF8Fbe1EA49">Live test</a>)</p><p>The second group of Pendle Ante Tests test the functions of the Pendle AMM implementation across their different markets. These both currently test 6 different markets (that use the 4 forges tested above).</p><p>From the Pendle <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.pendle.finance/docs/information/dive-deeper/pendle-amm">AMM documentation</a>, we see that the weights of the YT and the underlying token are set to 0.5 and 0.5 at the start of the market period, with the YT weight decreasing and underlying token weight increasing by the same amount over time until market expiry.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/379bfc743f5f583f86bce6231899166ea32995ce7ad25620257b9503d882403c.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>This test tests two characteristics that we should expect to see during proper AMM function given the above:</p><ul><li><p>During the entire market period, the sum of the two weights should always be 1</p></li><li><p>YT weight should always be less than or equal to the underlying token weight</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/db9ffdeb22621392e5a5fe56d98a030296167e136505098099425f9fe3a05169.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AntePendleMarketWeightTest.sol, lines 31–44</p><p>Note that the test ignores a market if it has entered the frozen period — at that point, the weights start to suffer from mathematical precision errors so the Pendle market stops shifting weights and trading.</p><h2 id="h-pendle-market-balance-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Pendle Market Balance Test</h2><p>(<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/38246ab9dc6b1fc51e203c33556b44851e42d4fb/contracts/pendle/AntePendleMarketBalanceTest.sol">Code</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xBfc5a7Db53AeCf2d5897a6abC371CF8A9743404B">Live test</a>)</p><p>The last Pendle Ante Test checks the same 6 markets to verify that the market’s assumptions about its internal token balances are correct, i.e. the market holds enough YT and underlying token in the actual token contracts to cover the amount of each the Pendle market has stored in internal state. A failure could indicate that the AMM got rugged, for example.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/95b1e1cf21f79a3989396677be42580628e84c9ebf945c0ded03311644ed5290.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>AntePendleMarketBalanceTest.sol, lines 28–46</p><p>Note that this test also excludes expired markets, but for a different reason: the <code>getReserves()</code> function has a known bug after the market has expired.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>We all know DeFi can be a dangerous place. Smart contracts can be opaque to your average DeFi user, and bad actors abound. Ante helps make code risk explicit by allowing for real-time financial guarantees around specific smart contract commitments. This helps you make more informed decisions about which protocols you might want to use. Responsible protocol teams like Pendle are helping pave the way for a safer Web3 future!</p><p>If you would like to learn more about how Ante could be useful for your protocol team, please reach out to us at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="mailto:hello@ante.finance">hello@ante.finance</a>, read the docs at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://docs.ante.finance/">docs.ante.finance</a>, or follow the team on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a> and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.gg/ante">Discord</a> for more Web3 security discussions!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante Tech Talk #3: Fixed-point Arithmetic and Rounding in AntePool]]></title>
            <link>https://paragraph.com/@ante-finance/ante-tech-talk-3-fixed-point-arithmetic-and-rounding-in-antepool</link>
            <guid>GqaDiDMgzjvna0k1TxH0</guid>
            <pubDate>Fri, 04 Feb 2022 22:46:15 GMT</pubDate>
            <description><![CDATA[Ante TeamThis continues a multi-part series walking through the Ante v0.5 protocol design as well as basic secure smart contract development practices. Check out Part 1 and Part 2. Today’s post covers an idiosyncrasy arising from the fact that all variables in the EVM are represented as integers rather than floats. This means that we must use integer arithmetic to simulate computations with real numbers. Though this problem also arises in “ordinary” programming, the adversarial nature of publ...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f639ef0af7266c3500451145216be508d3acbb6810c5fa751bff4656d33f726c.png" alt="Ante Team" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Ante Team</figcaption></figure><p><em>This continues a multi-part series walking through the Ante v0.5 protocol design as well as basic secure smart contract development practices. Check out </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/B7IVJfO61qi_mhSjlaUuPSfnotx1kir-IzMjLEi3n0g"><em>Part 1</em></a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/zFeUr2OO8pcbgHOzxamkbQNvMUTR5ETKHJ2DrKNAKik"><em>Part 2</em></a>.</p><p>Today’s post covers an idiosyncrasy arising from the fact that all variables in the EVM are represented as integers rather than floats. This means that we must use <strong>integer arithmetic</strong> to simulate computations with real numbers. Though this problem also arises in “ordinary” programming, the adversarial nature of public blockchains requires extra care.</p><h2 id="h-numerical-variables-in-evm-and-smart-contracts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Numerical variables in EVM and smart contracts</h2><p>On any computer, data is stored using discrete bits, but real numbers are usually represented up to some level of precision using <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Floating-point_arithmetic"><strong>floating-point arithmetic</strong></a>. When dealing with financial data, however, it is often advisable to use <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Fixed-point_arithmetic"><strong>fixed-point arithmetic</strong></a> instead to avoid possible issues with rounding or cross-platform reproducibility.</p><p>When writing smart contracts or writing on the EVM, these difficulties are compounded. First, gas costs are assessed on operations with 256-bit word size, meaning that floating-point operations incur additional gas costs. In addition, they are not natively included in Solidity, though it is <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol">possible</a> to implement them.</p><p>Second, smart contract programming often occurs in an <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.paradigm.xyz/2020/08/ethereum-is-a-dark-forest/">adversarial environment</a>. In such a setting, seemingly small rounding errors which would ordinarily be immaterial can compound and potentially be economically exploited by an attacker. Because we are dealing with variables which <em>directly determine</em> ownership of tokens or money, we must ensure that the choices of rounding used in fixed-point arithmetic do not impact protocol security.</p><h2 id="h-fixed-point-arithmetic-and-decay-math-in-antepool" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Fixed-point arithmetic and decay math in AntePool</h2><p>AntePool represents numerical constants such as the decay rate using fixed-point arithmetic with scaling factor <code>1e18</code>. In this post, we will focus on the usage of fixed-point arithmetic on the challenger side of the pool.</p><p>Recall from <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/antefinance.eth/zFeUr2OO8pcbgHOzxamkbQNvMUTR5ETKHJ2DrKNAKik">Part 2</a> that information about challengers is stored in the <code>challengerInfo</code> variable. Specifically, the total amount of ETH owned by challengers is given by <code>challengerInfo.totalAmount</code>, and the challenger balance of a given address <code>addr</code> is computed in <code>getStoredBalance()</code>by simulating a call of <code>updateDecay()</code> and then rounding the unrounded challenger balance:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ad89719fda361b5f81598b75a57bdbec0ec4488e76ef3c3ee786cc4bd2ddeafe.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Although the total balance would naturally be equal to the sum of each users’ balance if everything is computed to infinite precision, in practice the rounding involved in fixed-point arithmetic will make them unequal. Most importantly, we want to make sure that no sequence of operations can cause the sum of challenger balances to exceed the total amount of ETH owned by challengers, as this would make the AntePool insolvent! That is, we want to ensure that:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/626c48e9c71f551614e386bf561aed91f066565d73fe6f7f96eed7eaefe8f90d.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Secondly, any additional ETH in the total challenger side balance which is not attributed to any user is simply locked in the AntePool. We would like this amount to not grow too quickly. We call this quantity the <em>challenger excess balance</em>, with a similar definition for the staker side as well:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3dc8e4efd79120f12554f288c48173b7e9897508389be32b0c158d616110d6d7.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h2 id="h-empirically-characterizing-the-excess-balance" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Empirically characterizing the excess balance</h2><p>To get an initial sense for how the excess balance behaves, we used a randomized fuzz test to track it across a sequence of staking, challenging, and unstaking operations on a simulated blockchain. Specifically, we mocked a local testnet blockchain with <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/">Hardhat</a>, deployed a single AntePool, and ran 100 test iterations consisting of:</p><ul><li><p>from each of 10 test addresses, staking or challenging the pool with a random amount of ETH</p></li><li><p>advancing the chain for a random number of blocks</p></li><li><p>from each of 10 test addresses, unstaking from either the staker or challenger pool with a random amount of ETH</p></li><li><p>advancing the chain for a random number of blocks</p></li></ul><p>After each test iteration, we recorded the excess balance for both the staker and challenger pools, plotted in blue below.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1743b569edbac39415b0078a25e815cb56984c22feaf6391c31cc10b45c68ff8.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Excess balances accrued over time in a single run of our fuzz test</p><p>As the figure shows, in both staker and challenger pools, the excess balances are non-negative and stay extremely small. In fact, they remain on the order of 1,000s of wei even after 100 staking and unstaking iterations, which is an acceptable level for any practical usage.</p><p>However, this outcome is from just a single run of our fuzz test. Though we get similar results from more runs, how can we be sure that the excess balances <em>always</em> behave well? To get a greater level of certainty, in Part 4 of this series, we will analyze the situation theoretically and obtain provable upper bounds on the excess balances (shown in orange in the previous figure) which ensure they do not grow too quickly.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>To try out Ante for yourself, stake or challenge Ante Tests on Ante v0.5 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://app.ante.finance/"><strong>live</strong></a> on Mainnet now. If you’d like to get more involved, you can now <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.ante.finance/antev05/for-devs/writing-an-ante-test">write your own Ante Tests</a> or ask your favorite protocols to write and stake their own Ante Tests!</p><p>Let us know if you have any questions/comments, follow @AnteFinance on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a>, and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://ante.xyz/">Discord</a> for more discussion!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante Test Series #5: Olympus V2 - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-test-series-5-olympus-v2-ante-finance-medium</link>
            <guid>JEsOJAZ2obX3srTQpzzl</guid>
            <pubDate>Tue, 18 Jan 2022 18:16:19 GMT</pubDate>
            <description><![CDATA[gm frens! Welcome back to the Ante Test Series (check out our last writeup on Alchemix here). This week’s focus is everyone’s favorite Greco-mythical rebasing token, Olympus (OHM).Whence OHM?Olympus is an algorithmic reserve currency backed by decentralized assets that aims to be a standard store of value. Each OHM is backed at least 1:1 by 1 DAI equivalent of assets, and the price is is maintained above that level via buyback-and-burn (kind of the decentralized equivalent of a share repurcha...]]></description>
            <content:encoded><![CDATA[<br><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/287f2c1e9cdde7cf358db3d0fb20fd0cef74d0600d6ff63d67b94d1f1eeabe57.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>gm frens! Welcome back to the Ante Test Series (check out our last writeup on Alchemix <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/ante-finance/ante-test-series-4-alchemix-8569a5c0bc4">here</a>). This week’s focus is everyone’s favorite Greco-mythical rebasing token, <strong>Olympus (OHM)</strong>.</p><h2 id="h-whence-ohm" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Whence OHM?</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.olympusdao.finance/">Olympus</a> is an algorithmic reserve currency backed by decentralized assets that aims to be a standard store of value. Each OHM is backed at least 1:1 by 1 DAI equivalent of assets, and the price is is maintained above that level via buyback-and-burn (kind of the decentralized equivalent of a share repurchase program).</p><p>After tremendous growth in its first year (hitting nearly $900M in TVL at point), Olympus V2 was announced in Oct 2021 and migration commenced in Dec 2021. V2 Bonds went live recently with a cornucopia of upgraded features including updated payouts and vesting.</p><p>But IS it really backed? Ante Tests can verify.</p><p>Any time an upgrade or a new version of product is released, it’s important to verify that any desirable properties of the original still hold true (see our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/ante-finance/ante-test-series-1-compound-4e775fd8e1fc">Compound test writeup</a> for an example where a contract upgrade broke existing functionality). In this case, we can use an Ante Test to verify that OHMv2 continues to serve its stated purpose as a reserve currency by checking that it’s backed at least 1:1 by reserves and liquidity tokens in the Olympus treasury.</p><h2 id="h-checking-ohm-is-backed" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Checking OHM is backed</h2><p>The idea for an OHM backing test was originally proposed by Ante contributor <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/grokasm">grokasm</a> (view their test code for Olympus V1 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/67a8811fb0b3a531f3ca8cfc9a8ff0f41701540a/contracts/olympus/AnteOHMBackingTest.sol">here</a>). The test works by looping through the list of reserve and liquidity tokens in the Olympus treasury and comparing it to the total supply of OHM.</p><p>Checking the OHMv2 token supply is easy enough; we just call <code>totalSupply()</code> on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5">token contract</a>.</p><p>Getting the total treasury backing requires a little more work. The treasury address itself could change in the future and is now read through the <strong>OlympusAuthority</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x1c21f8ea7e39e2ba00bc12d2968d63f4acb38b7a">contract</a>. We implement the following helper function to return the current treasury address:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/020177ddcdd08ed092a6563b456270c2a179fbd27823b2c9659678efedef236a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>To sum up the total backing, we can iterate through the list of reserve and liquidity tokens in the treasury and add the value of each to a running total. Normally, we could check the registry of tokens in the Olympus treasury contract to get an up-to-date list of approved liquidity and reserve tokens. Unfortunately, the current version of the treasury contract does not have a functioning token registry, so we need to manually pass in the addresses of the approved liquidity and reserve tokens we want to check. The tokens approved at the time of our test deployment are: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x6b175474e89094c44da98b954eedeac495271d0f">DAI</a> (reserve token), <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x853d955acef822db058eb8505911ed77f175b99e">FRAX</a> (reserve token), and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0xb612c37688861f1f90761dc7f382c2af3a50cc39">OHM/FRAX SLP</a> (liquidity token).</p><p>*Note: Because the token addresses must be passed in manually through the constructor and cannot be changed after deployment, the Ante Test will not capture any token addresses subsequently added to or removed from the Olympus treasury token registry (a new Ante Test including any updated token addresses could be deployed if one wanted to include any changes in token addresses). ****This means that the Ante Test could fail even if OHM is still fully backed if Olympus changes the composition of their reserve and liquidity tokens. ***<em>If you are considering staking or challenging the OHMv2 Ante Test, as with any smart contract, you should review the code before interacting with it, and </em><strong><em>never</em></strong><em> deposit more than you can afford to lose.</em></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/619031456ab614a62f9364aa5dc2336919ee5844100835bcfa88be692e46f19a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>summing up reserve token balances</p><p>We loop through our list of reserve tokens, then loop through the list of liquidity tokens in a similar fashion to get the total treasury backing. Lastly, we compare the total backing against the supply of OHMv2 and fail the test if the OHM token is not fully backed by the Olympus treasury assets tested.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d0f6a7f369e0db9d0c6d6fd6203feabc7b156d732f0fc25c951877cbc2fe28ba.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>*scratchy prophetic voice* Should this fail, theomachy draws nigh</p><p>Check out the full test code <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/8545182b6dc6d67235694676fc4b3c0cf0d97fe7/contracts/olympus/AnteOHMV2BackingTest.sol">here</a>, and live test on Ante <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xD3Bc63Ccada2bA4F2D90B3a1be1C5c5738038Adb">here</a>!</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>When code is law, it’s important to verify that it works as intended if you don’t want to get <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rekt.news/leaderboard/">rekt</a>. Ante is a piece of Web3 infrastructure that makes on-chain guarantees easier to check. We hope fast-moving projects add Ante Tests to their launch checklist in the future (alongside audits, bug bounties, etc.) to provide their users with peace of mind that their innovative new features are working as specified.</p><p>We encourage everyone to write Ante Tests (Check out our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests">community GitHub</a> where other community members have written Ante Tests) and/or ask your favorite protocols to write and stake their own Ante Tests! Together, we can build a safer Web3 community!</p><p>What other protocols would you want to see Ante Tests written for? Let us know in the comments or via <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a>, and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.com/invite/yaJthzNdNG">Discord</a> for more Web3 security discussion!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante Tech Talk #2: Ante v0.5 Overview - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-tech-talk-2-ante-v0-5-overview-ante-finance-medium</link>
            <guid>hs7i4D02fmntpEkP53dM</guid>
            <pubDate>Thu, 13 Jan 2022 00:17:45 GMT</pubDate>
            <description><![CDATA[Ante in a nutshellAnte allows users to create incentivized on-chain guarantees of smart contract state that are programmatically settled. Users can either stake or challenge the pool, where payment on each side is asymmetrically determined based on the result of the corresponding Ante Test. Stakers benefit from the test continuing to pass by receiving a portion of challenger capital through a mechanism we call “decay”, while challengers receive a portion of staker capital upon test failure.Wh...]]></description>
            <content:encoded><![CDATA[<h2 id="h-ante-in-a-nutshell" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Ante in a nutshell</h2><p>Ante allows users to create incentivized on-chain guarantees of smart contract state that are programmatically settled. Users can either stake or challenge the pool, where payment on each side is asymmetrically determined based on the result of the corresponding Ante Test. Stakers benefit from the test continuing to pass by receiving a portion of challenger capital through a mechanism we call “decay”, while challengers receive a portion of staker capital upon test failure.</p><h2 id="h-what-does-this-mean" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What does this mean?</h2><p>One way to think about this is that Ante provides “financial verification” for smart contracts. Guarantees can be made about any testable on-chain condition, with payouts delivered programmatically upon test failure without requiring intermediaries/trusted third parties (see some examples of invariants that could be tested <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.ante.finance/antev05/for-devs/writing-an-ante-test/invariant-ideas">here</a>). Protocols that stake Ante Tests for their smart contracts are putting skin in the game, staking their confidence in the quality of their smart contracts with their own capital.</p><p>What’s more, community activity within the pool allow for an automatically generated <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.ante.finance/antev05/using-ante/trust-score">Decentralized Trust Score</a> that reflect the community’s trust in that particular protocol.</p><h2 id="h-how-we-designed-it" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How we designed it</h2><h2 id="h-architecture" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Architecture</h2><p>When creating the smart contracts for Ante, we decided to separate the test logic and stake/challenge/settlement pieces into separate <strong>AnteTest</strong> and <strong>AntePool</strong> functionalities. This provides a super lightweight framework for anyone to be able to write their own Ante Tests without having to worry about writing the settlement layer.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/05ec2821775c5660d16b2c4975db835fdddd42172496ee93922403621e02baf6.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Ante Tests contain test logic, while Ante Pools implement stake/challenge sides and wrap value transfer functions around it. This is handled programmatically via an Ante Pool Factory</p><p>Additionally, we handle deployment of Ante Pools using <strong>AntePoolFactory</strong>. Having Ante Pools deployed programmatically by the Ante Pool Factory means that users can self-serve deploy Ante Pools for their Ante Tests while being certain that every Ante Pool from that Factory behaves consistently. This greatly reduces the chance that any individual Ante Pool has a bug or flaw in its value transfer mechanism.</p><p><em>Note: Abstracting the user interaction layer away to Ante Pools does have certain drawbacks. For certain tests where we may have wanted to include checks for </em><code>msg.sender</code><em> in </em><code>checkTestPasses()</code><em>, because we call it through the Ante Pool contract the pool address becomes the sender.</em></p><h2 id="h-antetest-the-test-logic" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">AnteTest: the test logic</h2><p>In its most basic form, all an Ante Test needs is a test name and a <code>checkTestPasses()</code> function. Test writers can implement any number of additional helper functions as needed to implement more complex logic (e.g. a <code>checkpoint()</code> function to be able to calculate a TWAP between two points in time) as needed.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.ante.finance/antev05/for-devs/writing-an-ante-test/iantetest.sol-and-antetest.sol"><em>Read more</em></a>* about <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/5d7488e3dd7946a384f24b13f6a475b3ad709451/contracts/interfaces/IAnteTest.sol"><em>IAnteTest.sol</em></a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/5d7488e3dd7946a384f24b13f6a475b3ad709451/contracts/AnteTest.sol"><em>AnteTest.sol</em></a>.*</p><h2 id="h-antepool-staking-challenging-and-test-verification" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">AntePool: staking, challenging, and test verification</h2><p>In addition to being able to deposit/withdraw capital into either side of the pool, we wanted to add several time-based mechanisms in the AntePool contract to prevent certain undesirable behavior:</p><ul><li><p>Staker capital is locked upon staking and stakers have a 24-hour period between initiating a withdrawal and being able to withdraw their unlocked stake. This is to prevent the scenario in which a protocol that has staked their own protocol’s test from immediately withdrawing their stake upon receiving advance knowledge of an exploit. With the withdrawal period (unlocking), the protocol’s initiation of the withdrawal can serve as a warning signal to users.</p></li><li><p>Challengers must have challenged the test for at least 12 blocks before being able to call the <code>checkTest()</code> function. This is to prevent generalized frontrunning of a legitimate challenger trying to verify the test. (<em>Note that an “aspiring” frontrunner could still circumvent this by challenging small amounts of ETH into every Ante Pool</em>)</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6de48d55bc6e1fadb94d3cd6299065f73f064861ba239142aab7a05e22278dda.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Conceptual state diagram for an Ante Pool</p><p>To accomplish this, we have the following state variables that divide up the pool contract’s balance and track relevant user information:</p><pre data-type="codeBlock" text="PoolSideInfo public override stakingInfo;
PoolSideInfo public override challengerInfo;
ChallengerEligibilityInfo public override eligibilityInfo;
IterableAddressSetUtils.IterableAddressSet private challengers;
StakerWithdrawInfo public override withdrawInfo;
"><code>PoolSideInfo <span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> stakingInfo;
PoolSideInfo <span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> challengerInfo;
ChallengerEligibilityInfo <span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> eligibilityInfo;
IterableAddressSetUtils.IterableAddressSet <span class="hljs-keyword">private</span> challengers;
StakerWithdrawInfo <span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> withdrawInfo;
</code></pre><p><strong>stakingInfo</strong> and <strong>challengerInfo</strong> store the overall information (number of participants, total decay, decay multiplier) for each side of the pool. It also contains a mapping between wallet addresses and the corresponding stake/challenge information (amount, decay) for each address. When staking or otherwise interacting with the Ante Pool, we use a single <code>stake()</code> function with an <code>isChallenger</code> boolean to determine which <code>PoolSideInfo</code> to update.</p><p><strong>eligibilityInfo</strong> is used to track the most recent block each challenger has challenged the test so that we are able to enforce the 12-block minimum between challenging the test and calling checkTest().</p><p><strong>challengers</strong> is an iterable list of addresses that are currently challenging the test — this is used for checking that someone calling <code>checkTest()</code> has challenged the test as well as iterating through the list of challengers to calculate eligible payouts upon test failure.</p><p><strong>withdrawInfo</strong> stores information about overall and individual stakers withdrawing stake during the withdrawal waiting (unlocking) period.</p><p>The <strong>testNotFailed()</strong> modifier is used as a “require” statement around functions that should only be called (e.g. <code>stake()</code>) when the Ante Test has not failed.</p><p>Using these, we are able to implement stake/challenge sides of the pool, the staker withdrawal period, the challenger waiting period, and pre/post-failure user actions.</p><p>View <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/5d7488e3dd7946a384f24b13f6a475b3ad709451/contracts/interfaces/IAntePool.sol">IAntePool.sol</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/5d7488e3dd7946a384f24b13f6a475b3ad709451/contracts/AntePool.sol">AntePool.sol</a></p><h2 id="h-decay" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Decay</h2><p>Decay is a mechanism we introduced to incentivize stakers of an Ante Test by rewarding them with challenger capital if the test continues to pass. However, on a blockchain, only view functions are “free”. Continuously updating internal state variables like the amount of decay accumulated would require constantly spending gas to compute decay. To deal with this, we implement a helper <code>updateDecay()</code> function that calculates the accumulated decay up to that point and updates the stored decay balances. <code>updateDecay()</code> is then bundled into other function calls that require gas (e.g. <code>stake()</code>, <code>unstake()</code>, <code>checkTest()</code>) so that we can update the decay balances whenever those are called.</p><p><em>Note: because we are approximating a continuous function with discrete steps and also due to the nature of floating point arithmetic in Solidity, some deviation from “theoretical” decay is possible. Our next Tech Talk will dig into the implications of this in greater detail and talk about how we ensured that this never results in Ante Pool insolvency.</em></p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>There’s a lot more detail and thought that went into Ante v0.5 that we’ll dig into a future walkthrough, but hopefully this gives you a good sense of how we approached some of the protocol design decisions for Ante v0.5. Ante v0.5 is currently <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://app.ante.finance/"><strong>live</strong></a> on Mainnet and allows users to (among other things):</p><ul><li><p>stake/challenge/verify Ante Pools</p></li><li><p>Deploy your own Ante Pool from an Ante Test</p></li></ul><p>We have a lot of exciting enhancements for v0.5 as well as things in the pipeline for Ante v1.0 that we’re excited to share in the upcoming months.</p><p>We encourage everyone to write Ante Tests and/or ask your favorite protocols to write and stake their own Ante Tests! Together, we can build a safer DeFi community!</p><p>Let us know if you have any questions/comments, follow @AnteFinance on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a>, and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://discord.ante.finance/">Discord</a> for more discussion!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante Test Series #4: Alchemix - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-test-series-4-alchemix-ante-finance-medium</link>
            <guid>4Ksr2RKh7wjPng01VyUX</guid>
            <pubDate>Fri, 07 Jan 2022 04:50:41 GMT</pubDate>
            <description><![CDATA[Buenos días, amigos and welcome to the first edition of the Ante Test writing series in 2022. This week, we’re highlighting another community-written Ante test — a test written for Alchemix by waynebruce0x (who currently holds the #1 spot on the Ante Community Leaderboard). Alchemix is a protocol which lets DeFi users take out a loan against the future yield of their assets that slowly pays itself off. This is accomplished by letting users deposit collateral and subsequently mint a synthetic ...]]></description>
            <content:encoded><![CDATA[<br><p>Buenos días, amigos and welcome to the first edition of the Ante Test writing series in 2022. This week, we’re highlighting another community-written Ante test — a test written for Alchemix by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/waynebruce0x">waynebruce0x</a> (who currently holds the #1 spot on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/community-leaderboard">Ante Community Leaderboard</a>).</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://alchemix.fi/">Alchemix</a> is a protocol which lets DeFi users take out a loan against the future yield of their assets that slowly pays itself off. This is accomplished by letting users deposit collateral and subsequently mint a synthetic asset pegged 1:1 with that collateral. In order to withdraw the collateral again the user must repay the balance of the synthetic asset they borrowed, but this balance owed decreases over time until it eventually hits zero.</p><p>In the background, the collateral deposited is used to generate yield from other DeFi protocols. This synthetic asset can be transmuted or traded 1:1 into the underlying collateral fairly easily, effectively giving the user an advance on their future yield.</p><p><strong>alUSD doesn’t exceed DAI locked in Alchemix Test</strong></p><p>Waynebruce0x’s idea was to test that the total amount of synthetic asset outstanding was not more than the amount of underlying collateral — here specifically testing DAI and alUSD (an algo stablecoin minted using DAI collateral in alchemix).</p><p>Alchemix limits the amount of alUSD which can be minted from DAI to 50% of DAI deposited. If the amount of alUSD in circulation exceeded the DAI collateral in alchemix, it would indicate something had gone catastrophically wrong with the protocol. Such as a hacker draining DAI from the protocol or minting alUSD without depositing DAI. Fun fact — <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://slowmist.medium.com/slowmist-alchemix-hack-analysis-e8c9ec6c2ee3">this actually happened</a> in the case of alETH, Alchemix’s ETH-backed synthetic asset, back in June. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests/blob/main/contracts/alchemix/Ante_alETHSupplyTest.sol">Waynebruce0x also wrote a test for alETH which would have failed during the hack.</a></p><p>The test logic is fairly simple. First, check the total supply of alUSD, then the total amount of DAI controlled by the protocol. If the first quantity is more than the latter, the test fails. Otherwise, it holds true. This can be seen in the <code>checkTestPasses</code> function:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/933ca8757affcb0b13fcb6b7f61e6e55354e35cf6d1b987537974b8fc361b1ee.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The total DAI balance is computed as the sum of the DAI balances controlled by the Transmuters (contracts that maintain the peg by allowing alUSD to be turned into DAI 1:1) and being farmed in Yearn — <code>AlchemistYVAVL</code> and <code>TransmuterBYVAVL</code>. Astute code-readers will notice that there is a conversion step in which the yield bearing tokens held by these latter two contracts are converted to their equivalent DAI value via <code>PricePerShare</code></p><p>The actual addresses being tested are hardcoded in the contract:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/948e2509c2630054f7866966f00379704f9caf41f311a872c1bede6ae61ca9a6.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>This test and the corresponding Ante Pool were deployed on-chain and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xfA8348494B9de25aCBD389A7CF3E5C9EA71fc19c">can be viewed here</a>. AlUSD is currently fully backed by DAI and will hopefully continue to be solvent, but now degens have a way to parse the risk of failure in real-time without being solidity wizards.</p><p><strong>Conclusion</strong></p><p>You’ve probably heard it before, but <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rekt.news/leaderboard/">DeFi can be dangerous</a>. Hacks, exploits, and other shenanigans happen almost daily. There’s only so much we can do to prevent bugs from making it onto main-net, but as a community we can at least keep each other informed about the inherent risks involved.</p><p>Ante is an important piece of that puzzle, making DeFi safer by providing real-time risk assessments of protocol code failures — ultimately enabling you to make more informed decisions about where to park your hard-earned crypto. If that sounds interesting, then follow us on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/antefinance">twitter</a> and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.com/invite/ante">discord</a> (where waynebruce0x and other big brains hang out) to talk about the latest in web3 security.</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Wild Credit Interest Rate Calculation Bug Post-Mortem]]></title>
            <link>https://paragraph.com/@ante-finance/wild-credit-interest-rate-calculation-bug-post-mortem</link>
            <guid>MgEJBYTCZYQPHPBsl6ew</guid>
            <pubDate>Fri, 17 Dec 2021 22:14:58 GMT</pubDate>
            <description><![CDATA[Summary Lending markets are one of the core use cases of decentralized finance. Without them, we’d have to sell our favorite cryptos to ape into the newest 1000% APY farm. But thanks to protocols like Aave, Compound, Kashi, and Wild Credit, we can unlock the high APY potential of our favorite coins without sacrificing future gains. Wild Credit is a money market protocol that quickly gained a lot of attention due to its eye-poppingly high APRs, often offering upwards of 25% APR for supplying E...]]></description>
            <content:encoded><![CDATA[<br><p><strong>Summary</strong></p><p>Lending markets are one of the core use cases of decentralized finance. Without them, we’d have to sell our favorite cryptos to ape into the newest 1000% APY farm. But thanks to protocols like Aave, Compound, Kashi, and Wild Credit, we can unlock the high APY potential of our favorite coins without sacrificing future gains.</p><p>Wild Credit is a money market protocol that quickly gained a lot of attention due to its eye-poppingly high APRs, often offering upwards of 25% APR for supplying ETH and 45%+ APR for supplying stablecoins (and making them available for borrowing), much higher than other protocols at the time.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7ee5d9a5ede7eb1bd9f4791ea25560a1e8393c33907c5d6120849777d6d05653.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The Ante team was initially made aware of Wild Credit due to an <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xE76EEe525C0Bc488340Ff91167981db4A5C6391f">Ante Test</a> written by resident Antean <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/JSeam2/">jseam</a>. The high supply-side APR relative to the borrower interest paid made us question where the yield was coming from. Our investigation uncovered the answer — the utilization rate of the market was not being properly taken into account when calculating supplier interest accrued. This resulted in an accounting error that caused the protocol to owe more funds to its users than it actually contained.</p><p>At the time when the bug was discovered in late October, <strong>this deficit was increasing by over $100k/day</strong>. Though timely disclosure of the bug to the Wild Credit team prevented future losses, <strong>the deficit accrued by the protocol to that point already totaled around $14M.</strong></p><p>Key takeaway— <strong>if something seems too good to be true, it probably is (even in crypto).</strong></p><p><strong>Vulnerability</strong></p><p>Without loss of generality, let’s examine the DAI side of the DAI-ETH lending pair deployed here (now no longer in use): <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x3550e61886E1184B8BB732bb7135BDA9B7461801">https://etherscan.io/address/0x3550e61886E1184B8BB732bb7135BDA9B7461801</a></p><p>Currently, DAI suppliers users accrue interest on their DAI balance every time the <code>accrueAccount</code> is called (when the user deposits or withdraws collateral and takes out or repays a loan). This is seen in the following code:</p><pre data-type="codeBlock" text="function accrueAccount(address _account) public {
    _distributeReward(_account);
    accrue();
    _accrueAccountInterest(_account);

    if (_account != feeRecipient()) {
      _accrueAccountInterest(feeRecipient());
    }
  }
"><code>function <span class="hljs-built_in">accrueAccount</span>(address _account) public {
    <span class="hljs-built_in">_distributeReward</span>(_account);
    <span class="hljs-built_in">accrue</span>();
    <span class="hljs-built_in">_accrueAccountInterest</span>(_account);

    if (_account != feeRecipient()) {
      <span class="hljs-built_in">_accrueAccountInterest</span>(feeRecipient());
    }
  }
</code></pre><p>The <code>accrue</code> function called here calculates the <code>cumulativeInterestRate</code> paid by borrowers. This <code>cumulativeInterestRate</code> is then used to calculate the interest paid to suppliers in <code>_accrueAccountInterest</code> as shown below:</p><pre data-type="codeBlock" text="function _accrueAccountInterest(address _account) internal {
    uint lpBalanceA = lpToken[tokenA].balanceOf(_account);
    uint lpBalanceB = lpToken[tokenB].balanceOf(_account);

    _accrueAccountSupply(tokenA, lpBalanceA, _account);
    _accrueAccountSupply(tokenB, lpBalanceB, _account);
    _accrueAccountDebt(tokenA, _account);
    _accrueAccountDebt(tokenB, _account);

    accountInterestSnapshot[tokenA][_account] = cumulativeInterestRate[tokenA];
    accountInterestSnapshot[tokenB][_account] = cumulativeInterestRate[tokenB];
  }

  function _accrueAccountSupply(address _token, uint _amount, address _account) internal {
    if (_amount &gt; 0) {
      uint supplyInterest   = _newInterest(_amount, _token, _account);
      uint newSupplyAccount = supplyInterest * _lpRate(_token) / 100e18;
      uint newSupplySystem  = supplyInterest * _systemRate(_token) / 100e18;

      _mintSupply(_token, _account, newSupplyAccount);
      _mintSupply(_token, feeRecipient(), newSupplySystem);
    }
  }
"><code>function <span class="hljs-built_in">_accrueAccountInterest</span>(address _account) internal {
    uint lpBalanceA = lpToken<span class="hljs-selector-attr">[tokenA]</span><span class="hljs-selector-class">.balanceOf</span>(_account);
    uint lpBalanceB = lpToken<span class="hljs-selector-attr">[tokenB]</span><span class="hljs-selector-class">.balanceOf</span>(_account);

    <span class="hljs-built_in">_accrueAccountSupply</span>(tokenA, lpBalanceA, _account);
    <span class="hljs-built_in">_accrueAccountSupply</span>(tokenB, lpBalanceB, _account);
    <span class="hljs-built_in">_accrueAccountDebt</span>(tokenA, _account);
    <span class="hljs-built_in">_accrueAccountDebt</span>(tokenB, _account);

    accountInterestSnapshot<span class="hljs-selector-attr">[tokenA]</span><span class="hljs-selector-attr">[_account]</span> = cumulativeInterestRate<span class="hljs-selector-attr">[tokenA]</span>;
    accountInterestSnapshot<span class="hljs-selector-attr">[tokenB]</span><span class="hljs-selector-attr">[_account]</span> = cumulativeInterestRate<span class="hljs-selector-attr">[tokenB]</span>;
  }

  function <span class="hljs-built_in">_accrueAccountSupply</span>(address _token, uint _amount, address _account) internal {
    if (_amount > <span class="hljs-number">0</span>) {
      uint supplyInterest   = <span class="hljs-built_in">_newInterest</span>(_amount, _token, _account);
      uint newSupplyAccount = supplyInterest * <span class="hljs-built_in">_lpRate</span>(_token) / <span class="hljs-number">100</span>e18;
      uint newSupplySystem  = supplyInterest * <span class="hljs-built_in">_systemRate</span>(_token) / <span class="hljs-number">100</span>e18;

      <span class="hljs-built_in">_mintSupply</span>(_token, _account, newSupplyAccount);
      <span class="hljs-built_in">_mintSupply</span>(_token, feeRecipient(), newSupplySystem);
    }
  }
</code></pre><p>The <code>_newInterest</code> accrued to suppliers is calculated without considering the ratio of assets supplied to assets borrowed, resulting in an overestimate of the interest accrued:</p><pre data-type="codeBlock" text="function _newInterest(uint _balance, address _token, address _account) internal view returns(uint) {
    uint currentCumulativeRate = cumulativeInterestRate[_token] + _pendingInterestRate(_token);
    return _balance * (currentCumulativeRate - accountInterestSnapshot[_token][_account]) / 100e18;
  }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_newInterest</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> _balance, <span class="hljs-keyword">address</span> _token, <span class="hljs-keyword">address</span> _account</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
    <span class="hljs-keyword">uint</span> currentCumulativeRate <span class="hljs-operator">=</span> cumulativeInterestRate[_token] <span class="hljs-operator">+</span> _pendingInterestRate(_token);
    <span class="hljs-keyword">return</span> _balance <span class="hljs-operator">*</span> (currentCumulativeRate <span class="hljs-operator">-</span> accountInterestSnapshot[_token][_account]) <span class="hljs-operator">/</span> <span class="hljs-number">100e18</span>;
  }
</code></pre><p>The correct calculation would change the return statement in <code>_newInterest</code> as described in the following pseudocode:</p><pre data-type="codeBlock" text="return _balance * (debt/supply) * (currentCumulativeRate - accountInterestSnapshot[_token][_account]) / 100e18;
"><code><span class="hljs-keyword">return</span> _balance <span class="hljs-operator">*</span> (debt<span class="hljs-operator">/</span>supply) <span class="hljs-operator">*</span> (currentCumulativeRate <span class="hljs-operator">-</span> accountInterestSnapshot[_token][_account]) <span class="hljs-operator">/</span> <span class="hljs-number">100e18</span>;
</code></pre><p>Writing bug-free code is hard, and the stakes are high on-chain. Here, a one-line bug caused an 8 figure loss in user funds!</p><p><em>NB: _lpRate and _systemRate are both set to 50% and do not affect the proof of concept</em></p><p><strong>Example</strong></p><p>Assume the borrow rate for the ETH-DAI market is 94.7% and 1000 DAI are supplied to the market, 200 DAI borrowed.</p><p>The APR paid to suppliers is set at 50% of the borrow rate (the <code>_lpRate</code> above).</p><p>Thus while borrowers are paying an interest of 189 DAI per year (0.947 * 200), suppliers are “earning” 473 DAI per year (0.473 * 1000), <strong>resulting in a net deficit to the protocol of 284 DAI per year.</strong> Repeat this calculation using the real parameters and across all lending markets to calculate the full impact of the bug.</p><p><strong>Fix</strong></p><p>The Wild Credit team moved swiftly to mitigate further losses from the protocol by (1) pausing all borrowing/supplying in the contracts and (2) moving all funds in their lending markets to the protocol treasury.</p><p>Following this, the team calculated their users’ total supplied balances net of their borrowed balances and compared this quantity to the funds present in the protocol. They determined that the total deficit amounted to 22% of user funds and this loss was socialized.</p><p>Users were refunded proportionally from the protocol assets and issued wBOND tokens equal to the deficit amount. These wBOND tokens are set to mature at $1 with no fixed expiration, and will be paid off using future protocol revenue.</p><p><strong>Acknowledgments</strong></p><p>We’d like to acknowledge Wild Credit for their swift and effective harm mitigation and commitment to making their users whole. We’d also like to thank Immunefi for their guidance and support during the disclosure process. Additionally, we’d like to acknowledge members of Cluster Capital for discussions which led to the discovery of the issue.</p><p>Finally, we’d like to thank our community member <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/JSeam2">jseam</a> for writing an <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xE76EEe525C0Bc488340Ff91167981db4A5C6391f">Ante Test</a> for Wild Credit and bringing the protocol to our attention. As part of this post-mortem and as a show of support for the Wild Credit team going forward, the Ante team will be staking our portion of the bounty payout (~2 ETH) in jseam’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xE76EEe525C0Bc488340Ff91167981db4A5C6391f">Ante Test</a>, which assesses the integrity of Wild Credit’s price oracles.</p><p>To find out more about how Ante Tests enable monetary piece of mind in DeFi and connect with other security-conscious degens, follow us on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/antefinance">Twitter</a> and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://discord.gg/yaJthzNdNG">Discord</a>.</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante Test Series #2: Ante Finance - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-test-series-2-ante-finance-ante-finance-medium</link>
            <guid>HYpdzmvYiolp4eNH0TyY</guid>
            <pubDate>Thu, 02 Dec 2021 15:54:21 GMT</pubDate>
            <description><![CDATA[gm frens! Welcome back to the Ante Test Series (check out our first writeup on Compound here, or read more here if you need a refresher on Ante Tests). At Ante, we believe in putting our money where our mouth is, so it’s only natural that this week’s featured Ante Tests are tests for the Ante protocol! After all, what kind of buidlers would we be if we didn’t eat our own dog food?About the testsBoth of these Ante Tests loop over multiple contract addresses checking for specific conditions. Wh...]]></description>
            <content:encoded><![CDATA[<br><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/73364ec17d8edacf7fda374e7753a6009907d6556a38e7d4d9a89afce03a2df1.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>gm frens! Welcome back to the Ante Test Series (check out our first writeup on Compound <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/ante-finance/ante-test-series-1-compound-4e775fd8e1fc">here</a>, or read more <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/ante-finance/why-ante-f206ccef6cba">here</a> if you need a refresher on Ante Tests).</p><p>At Ante, we believe in putting our money where our mouth is, so it’s only natural that this week’s featured Ante Tests are tests for the <strong>Ante protocol</strong>! After all, what kind of buidlers would we be if we didn’t eat our own dog food?</p><h2 id="h-about-the-tests" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">About the tests</h2><p>Both of these Ante Tests loop over multiple contract addresses checking for specific conditions. While looping in general can be susceptible to a block stuffing attack if the number of tests in the loop gets sufficiently (read: extremely) high, we set the array of tests on deployment explicitly so we can avoid this problem.</p><pre data-type="codeBlock" text="constructor(address[] memory antePoolContracts) {
    testedContracts = antePoolContracts;
    protocolName = &quot;Ante&quot;;
}
"><code>constructor(address<span class="hljs-section">[]</span> memory antePoolContracts) {
    <span class="hljs-attr">testedContracts</span> = antePoolContracts<span class="hljs-comment">;</span>
    <span class="hljs-attr">protocolName</span> = <span class="hljs-string">"Ante"</span><span class="hljs-comment">;</span>
}
</code></pre><p>Having the tested contracts be passed in as an argument on deploy also makes it easy to deploy new versions of the test if the set of Ante Pools we want to check changes.</p><h2 id="h-antepooltest" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">AntePoolTest</h2><p>AntePoolTest checks several Ante Pools to confirm that the balance matches the total amount staked, challenged, and paid out (check it out on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xDC99AD0b3FDdAE6522e26c33439a0b0b476172c5">Ante app</a>). This is an example of using an Ante Test to verify that smart contract functionality works as intended.</p><pre data-type="codeBlock" text="function checkTestPasses() public view override returns (bool) {
    for (uint256 i = 0; i &lt; testedContracts.length; i++) {
        IAntePool antePool = IAntePool(testedContracts[i]);
        // totalPaidOut should be 0 before test fails
        if (
            testedContracts[i].balance &lt; 
            (
                antePool
                    .getTotalChallengerStaked()
                    .add(antePool.getTotalStaked())
                    .add(antePool.getTotalPendingWithdraw())
                    .sub(antePool.totalPaidOut())
            )
        ) {
            return false;
        }
    }
    return true;
}
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkTestPasses</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&#x3C;</span> testedContracts.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
        IAntePool antePool <span class="hljs-operator">=</span> IAntePool(testedContracts[i]);
        <span class="hljs-comment">// totalPaidOut should be 0 before test fails</span>
        <span class="hljs-keyword">if</span> (
            testedContracts[i].<span class="hljs-built_in">balance</span> <span class="hljs-operator">&#x3C;</span> 
            (
                antePool
                    .getTotalChallengerStaked()
                    .add(antePool.getTotalStaked())
                    .add(antePool.getTotalPendingWithdraw())
                    .sub(antePool.totalPaidOut())
            )
        ) {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        }
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
</code></pre><p>When AntePoolTest was deployed, there were 6 Ante Pools on mainnet, so AntePoolTest checks each of those 6 pools and if any of them fail to meet the conditions, AntePoolTest fails.</p><h2 id="h-anteavldroptest" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">AnteAVLDropTest</h2><p>Our second (and brand new) Ante Test for Ante is a <strong>plunge protection test</strong> to make sure that there isn’t a 99% drop in value locked across the tested contracts (check it out <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0x2EdC35B39BFBca6A52eA35612C2684D3D7654763">here</a>). In the test, we define a helper function <code>getCurrentAVL()</code>, which loops through the Ante Pools and sums up the balances:</p><pre data-type="codeBlock" text="function getCurrentAVL() public view returns (uint256) {
    uint256 currentAVL;

        for (uint256 i = 0; i &lt; testedContracts.length; i++) {
        currentAVL = currentAVL.add(testedContracts[i].balance);
    }

    return currentAVL;
}
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCurrentAVL</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></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> currentAVL;

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&#x3C;</span> testedContracts.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
        currentAVL <span class="hljs-operator">=</span> currentAVL.add(testedContracts[i].<span class="hljs-built_in">balance</span>);
    }

    <span class="hljs-keyword">return</span> currentAVL;
}
</code></pre><p>In the constructor, a snapshot of the total AVL is taken on deploy and used to calculate the failure threshold. For the current deployment, we’ve included all 11 Ante Tests that are currently on Mainnet, which includes 4 community-written tests 🥳.</p><pre data-type="codeBlock" text="constructor(address[] memory _testedContracts) {
    protocolName = &quot;Ante&quot;;
    testedContracts = _testedContracts;// Calculate test failure threshold using 99% drop in total AVL at time of deploy
    avlThreshold = getCurrentAVL().div(100);
}
"><code>constructor(address<span class="hljs-section">[]</span> memory _testedContracts) {
    <span class="hljs-attr">protocolName</span> = <span class="hljs-string">"Ante"</span><span class="hljs-comment">;</span>
    <span class="hljs-attr">testedContracts</span> = _testedContracts<span class="hljs-comment">;// Calculate test failure threshold using 99% drop in total AVL at time of deploy</span>
    <span class="hljs-attr">avlThreshold</span> = getCurrentAVL().div(<span class="hljs-number">100</span>)<span class="hljs-comment">;</span>
}
</code></pre><p>Once we have our AVL threshold, checking the failure condition is pretty straightforward:</p><pre data-type="codeBlock" text="function checkTestPasses() public view override returns (bool) {
    return getCurrentAVL() &gt;= avlThreshold;
}
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkTestPasses</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
    <span class="hljs-keyword">return</span> getCurrentAVL() <span class="hljs-operator">></span><span class="hljs-operator">=</span> avlThreshold;
}
</code></pre><p>Dead simple, right? Honestly, besides helping bootstrap trust in a protocol, writing an Ante Test is also a great way to onboard junior developers and teach them basic smart contract development. I mean, our UX designer wrote AnteAVLDropTest!</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>Risks in DeFi are really hard to understand unless you’re super technical. Ante Tests help quantify those risks in a simple manner, and we’ve made it super easy for anyone to write your own Ante Tests. Check out our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests">community GitHub</a> where other community members have written Ante Tests for protocols like OlympusDAO and Wild Credit and help write tests for your favorite protocols, follow us on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a>, and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.com/invite/yaJthzNdNG">Discord</a> for more discussion!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[ANTE Test Series #1: Compound - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-test-series-1-compound-ante-finance-medium</link>
            <guid>EWKQnSev4TggpLjpRhKc</guid>
            <pubDate>Fri, 26 Nov 2021 17:31:25 GMT</pubDate>
            <description><![CDATA[gm frens, and welcome to the first article in our Ante Test Series. Each week, we’ll highlight Ante Tests deployed on-chain: what they do, why we wrote them, and why you should care (learn more about Ante Tests here). To kick things off, we’ll start with two Ante Tests our core team wrote for Compound and submitted to the EthGlobal hackathon. Our submission won the Compound grant and the prize money was staked in the Ante Tests on-chain. $COMP (Comptroller) Issuance Rate Test On September 29t...]]></description>
            <content:encoded><![CDATA[<br><p>gm frens, and welcome to the first article in our Ante Test Series. Each week, we’ll highlight Ante Tests deployed on-chain: what they do, why we wrote them, and why you should care (learn more about Ante Tests <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/ante-finance/why-ante-f206ccef6cba">here</a>).</p><p>To kick things off, we’ll start with two Ante Tests our core team wrote for Compound and submitted to the EthGlobal hackathon. Our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://showcase.ethglobal.com/ethonline2021/ante-finance">submission</a> won the Compound grant and the prize money was staked in the Ante Tests on-chain.</p><p><strong>$COMP (Comptroller) Issuance Rate Test</strong></p><p>On September 29th, Compound introduced a bug into their Comptroller contract via a governance-approved upgrade. This bug allowed certain users to claim significantly more $COMP awards than they were entitled to, leading to $90M being drained from the protocol in a span of 48 hours.</p><p>Our Issuance Rate Test fails if such an event occurs again. The test logic snapshots the current Comptroller $COMP balance whenever the <code>checkpoint</code> function is called, and also once when the contract is deployed. Then, the current $COMP balance is checked against the snapshotted balance whenever <code>checkTestPasses</code> is called:</p><pre data-type="codeBlock" text="function checkTestPasses() public view override returns (bool) {
        uint256 timeSinceLastCheckpoint = block.timestamp.sub(lastCheckpointTime);
        if (timeSinceLastCheckpoint &gt; MIN_PERIOD) {
            uint256 compBalance = COMP.balanceOf(COMPTROLLER);
            // if COMP was added to contract then return true to avoid reversion due to underflow
            if (compBalance &gt;= lastCompBalance) {
                return true;
            }            return lastCompBalance.sub(compBalance).div(timeSinceLastCheckpoint) &lt; COMP_PER_SEC_THRESHOLD;
        }        // if timeSinceLastCheckpoint is less than MIN_PERIOD just return true
        // don&apos;t revert test since this will trigger failure on associated AntePool
        return true;
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkTestPasses</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-keyword">uint256</span> timeSinceLastCheckpoint <span class="hljs-operator">=</span> <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span>.sub(lastCheckpointTime);
        <span class="hljs-keyword">if</span> (timeSinceLastCheckpoint <span class="hljs-operator">></span> MIN_PERIOD) {
            <span class="hljs-keyword">uint256</span> compBalance <span class="hljs-operator">=</span> COMP.balanceOf(COMPTROLLER);
            <span class="hljs-comment">// if COMP was added to contract then return true to avoid reversion due to underflow</span>
            <span class="hljs-keyword">if</span> (compBalance <span class="hljs-operator">></span><span class="hljs-operator">=</span> lastCompBalance) {
                <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
            }            <span class="hljs-keyword">return</span> lastCompBalance.sub(compBalance).div(timeSinceLastCheckpoint) <span class="hljs-operator">&#x3C;</span> COMP_PER_SEC_THRESHOLD;
        }        <span class="hljs-comment">// if timeSinceLastCheckpoint is less than MIN_PERIOD just return true</span>
        <span class="hljs-comment">// don't revert test since this will trigger failure on associated AntePool</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
</code></pre><p>If the rate of $COMP decrease is ever greater than 10,000 $COMP/day, as it was when the bug was introduced, the test will fail. To prevent abuse and false positives, the <code>checkpoint</code> function can only be called once every 48 hours and at least 12 hours must have passed since the last checkpoint before the test can fail.</p><p>This functions as a <strong>live, on-chain regression test</strong> for re-occurrence of this bug. DeFi users staking and challenging this test asynchronously produce real-time measurements of community trust that the bug won’t be re-introduced. These measurements will become particularly interesting as further upgrades to the Comptroller contract are made.</p><p><strong>Compound Markets TVL Drop Test</strong></p><p>Encapsulating the risk of catastrophic protocol failure in a few lines of code can be tricky business. In some cases however, the Total Value Locked (TVL) functions as a proxy. If the TVL plunges, it can indicate that a hack has occurred or that a bug has caused a loss of user funds or user confidence. Testing for a drop in TVL therefore equivalently tests for a wide variety of failure modes — particularly in the case of lending markets.</p><p>This is the motivation behind this test — if the TVL in any of Compound’s top 5 markets falls by over 90%, it indicates that Compound itself has likely suffered serious damage. The TVL in each of these markets is snapshotted on test deploy:</p><pre data-type="codeBlock" text="constructor() {
        protocolName = &quot;Compound&quot;;        for (uint256 i = 0; i &lt; 5; i++) {
            ICToken cToken = cTokens[i];
            testedContracts.push(address(cToken));            thresholds[i] = ((cToken.getCash() + cToken.totalBorrows()) * PERCENT_DROP_THRESHOLD) / 100;
        }
    }
"><code><span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{
        protocolName <span class="hljs-operator">=</span> <span class="hljs-string">"Compound"</span>;        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">5</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
            ICToken cToken <span class="hljs-operator">=</span> cTokens[i];
            testedContracts.<span class="hljs-built_in">push</span>(<span class="hljs-keyword">address</span>(cToken));            thresholds[i] <span class="hljs-operator">=</span> ((cToken.getCash() <span class="hljs-operator">+</span> cToken.totalBorrows()) <span class="hljs-operator">*</span> PERCENT_DROP_THRESHOLD) <span class="hljs-operator">/</span> <span class="hljs-number">100</span>;
        }
    }
</code></pre><p>and <code>checkTestPasses</code> checks whether that TVL has dropped severely:</p><pre data-type="codeBlock" text="function checkTestPasses() public view override returns (bool) {
        for (uint256 i = 0; i &lt; 5; i++) {
            ICToken cToken = cTokens[i];
            if ((cToken.getCash() + cToken.totalBorrows()) &lt; thresholds[i]) {
                return false;
            }
        }        return true;
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkTestPasses</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">5</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
            ICToken cToken <span class="hljs-operator">=</span> cTokens[i];
            <span class="hljs-keyword">if</span> ((cToken.getCash() <span class="hljs-operator">+</span> cToken.totalBorrows()) <span class="hljs-operator">&#x3C;</span> thresholds[i]) {
                <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
            }
        }        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
</code></pre><p>This test will fail (i.e., return <code>false</code> ) only if Compound itself fails, and thus staker and challenger actions on this pool <strong>provide real-time plunge protection</strong>. Pretty cool.</p><p><strong>Conclusion</strong></p><p>Check out our Compound Ante Tests <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0xc74b762547C5773FC02868c1Fad71C0dB9ecF36c">here</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.ante.finance/#/contract/0x7e92090eA1835e259664c387Dcd1c2B5D9F0144b">here</a>. You can stake in support or, if you think they might fail, you can challenge them.</p><p>DeFi is pretty amazing. We came together as anons to build a new financial system — and we built it using cats, frogs, anime, and food memes. All while making lasting friends along the way. It’s also pretty scary. Unless you’re a super coder, you really can’t tell if or how likely it is that you’re going to lose all of your hard-earned crypto. Audits, bug bounties, and insurance help — but none of these are perfect tools.</p><p>Here at Ante, we’re trying to make DeFi just a little less scary, or at least just make that scariness legible. Imagine a future where you can see which protocols have staked money behind their code, the perceived risk of these protocols to exploits in real-time, and <strong>even build on top of this information in a composable way</strong>. If that sounds interesting to you, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-community-tests">join us</a> and other security-conscious degens in building the new economy of trust.</p><p>For more info on protocol mechanics and Ante Tests, subscribe to our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/AnteFinance">Twitter</a> and join our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.co/SybMc4I8Ac?amp=1">Discord</a>.</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Ante Tech Talk #1: Checks-Effects-Interactions - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/ante-tech-talk-1-checks-effects-interactions-ante-finance-medium</link>
            <guid>jwqEzHehmbVc9WQyGHcC</guid>
            <pubDate>Tue, 23 Nov 2021 03:18:55 GMT</pubDate>
            <description><![CDATA[What is CEI?Checks-Effects-Interactions is a pattern that helps minimize the attack surface area of smart contracts by ordering control flow:First, run checks (e.g., sanity checks, safety checks of potential state changes)Next, apply internal effects (e.g., in-contract variable and parameter changes)Lastly, conduct external interactions (e.g., interactions with external contracts and/or sending of ETH)This might feel unintuitive to someone coming from Web 2.0 where you might typically apply e...]]></description>
            <content:encoded><![CDATA[<h2 id="h-what-is-cei" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What is CEI?</h2><p><strong>Checks-Effects-Interactions</strong> is a pattern that helps minimize the attack surface area of smart contracts by ordering control flow:</p><ol><li><p>First, run <strong>checks</strong> (e.g., sanity checks, safety checks of potential state changes)</p></li><li><p>Next, apply internal <strong>effects</strong> (e.g., in-contract variable and parameter changes)</p></li><li><p>Lastly, conduct external <strong>interactions</strong> (e.g., interactions with external contracts and/or sending of ETH)</p></li></ol><p>This might feel unintuitive to someone coming from Web 2.0 where you might typically apply effects after interactions. However, in Solidity, this would open the function up to an attack via <strong>reentrancy</strong> (of which <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.coindesk.com/understanding-dao-hack-journalists">The DAO hack</a> is probably the most well-known example). In Solidity, when a value transfer of ETH occurs a <code>payable</code> function can be automatically invoked — a malicious actor could write this function in a way to potentially exploit the interacted contract. By checking state and applying effects before external interactions, we can make it more difficult for a potential attacker to create a scenario where a malicious contract is able to repeatedly call functions that should only be called once.</p><h2 id="h-cei-example-claim-in-antepoolsol" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">CEI example: claim() in AntePool.sol</h2><p>To see this pattern in action, let’s take a look at the <code>claim()</code> function in <strong>AntePool.sol</strong>:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/19a86d65d86a33175646735ca6528268cee0f8b43f58ad7a92ae5d7648e4d0fb.png" alt="Code snippet of the claim() function within AntePool.sol" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Code snippet of the claim() function within AntePool.sol</figcaption></figure><p>Lines 318–334 in <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/antefinance/ante-v0-core/blob/71bb139aa1e506bba4f53b979e6ace1900ea2a50/contracts/AntePool.sol">AntePool.sol</a></p><p>As a refresher, Ante allows users to create incentivized on-chain guarantees of smart contract state that are programmatically settled. Since <code>claim()</code> is one of the primary value transfer functions for the Ante protocol, it is critical that we prevent improper withdrawals from a pool. Let’s break down how we use the CEI pattern here to guard against some common attack vectors.</p><h2 id="h-checks" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Checks</h2><p>We conduct two checks here to verify that the person calling <code>claim()</code> is an eligible claimant:</p><pre data-type="codeBlock" text="require(pendingFailure, “ANTE: Test has not failed”);
require(user.startAmount &gt; 0, “ANTE: No Challenger Staking balance”);
"><code><span class="hljs-built_in">require</span>(pendingFailure, “ANTE: Test has not failed”);
<span class="hljs-built_in">require</span>(user.startAmount <span class="hljs-operator">></span> <span class="hljs-number">0</span>, “ANTE: No Challenger Staking balance”);
</code></pre><p>First, we check that the Ante Test has failed. This prevents people from claiming from an active test. Next, we check that user has a challenge balance greater than zero — since one must challenge the Ante Test in order to be eligible to claim a payout from its failure, this prevents people that haven’t challenged the test from claiming a share that doesn’t belong to them.</p><h2 id="h-effects" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Effects</h2><p>Now that we’ve verified that the sender is an eligible claimant, we can calculate the payout amount and apply the following effects:</p><pre data-type="codeBlock" text="user.startAmount = 0;
numPaidOut = numPaidOut.add(1);
totalPaidOut = totalPaidOut.add(amount);
"><code><span class="hljs-attr">user.startAmount</span> = <span class="hljs-number">0</span><span class="hljs-comment">;</span>
<span class="hljs-attr">numPaidOut</span> = numPaidOut.add(<span class="hljs-number">1</span>)<span class="hljs-comment">;</span>
<span class="hljs-attr">totalPaidOut</span> = totalPaidOut.add(amount)<span class="hljs-comment">;</span>
</code></pre><p>The important bit here is that we zero out the challenger balance <strong>before</strong> we transfer any value so that the user can’t claim again via reentrancy. If they were to attempt this, since the user’s balance is now 0 the initial checks would fail and only one value transfer will go through.</p><p>We also increase the count for number of payouts and total amount paid out but this is less important as it doesn’t affect value transfer or calculation.</p><h2 id="h-interactions" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Interactions</h2><pre data-type="codeBlock" text="_safeTransfer(msg.sender, amount);
emit ClaimPaid(msg.sender, amount);
"><code>_safeTransfer(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, amount);
<span class="hljs-keyword">emit</span> ClaimPaid(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, amount);
</code></pre><p>Finally, we use <code>_safeTransfer</code> to send value to challenger and emit the <code>ClaimPaid</code> event. (Note: in this implementation of <code>_safeTransfer</code> we send the lesser of the pool balance and the amount owed in the likely impossible edge case that rounding errors cause the pool to not have enough ETH)</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
        <item>
            <title><![CDATA[Trust in DeFi - Ante Finance - Medium]]></title>
            <link>https://paragraph.com/@ante-finance/trust-in-defi-ante-finance-medium</link>
            <guid>iiidR8KjfKUlSxUwKPSf</guid>
            <pubDate>Fri, 12 Nov 2021 15:26:58 GMT</pubDate>
            <description><![CDATA[Author: DeFinnDeFi has experienced a momentous surge in interest and adoption over the last several years. Since early 2020, the total value locked (“TVL”) on DeFi protocols has increased over 100x and as of this writing, TVL is over $115 billion. On December 4, 2020, the DeFi ecosystem exceeded one million unique wallet addresses and, less than five months later, exceeded two million.DeFi adoption still pales in comparison to both the crypto and global lending markets, at roughly 5% and 1.5%...]]></description>
            <content:encoded><![CDATA[<h3 id="h-author-definn" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Author: DeFinn</h3><p>DeFi has experienced a momentous surge in interest and adoption over the last several years. Since early 2020, the total value locked (“TVL”) on DeFi protocols has increased over 100x and as of this writing, TVL is over <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://defillama.com/home">$115 billion</a>. On December 4, 2020, the DeFi ecosystem exceeded one million unique wallet addresses and, less than five months later, exceeded two million.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1002e4c2a4034c13126920c9f449400b4ec786372cde8bd9b06a125555cc44e9.jpg" 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>DeFi adoption still pales in comparison to both the crypto and global lending markets, at roughly 5% and 1.5%, respectively. Readers here are no strangers to the innovation and potential that exists in DeFi, so what is the main obstacle to adoption and acceptance of DeFi among institutional and retail investors?</p><p>In a word, trust. Trust that the system is secure and legitimate, with staying power to be a commonly used financial system for the future. Trust that of the many DeFi projects out there, the ones gaining use are the ones that will endure.</p><p><strong>Inertia Towards TradFi</strong></p><p>Inertia in Tradfi is powerful. Most people are used to traditional financial institutions and, consciously or not, equate familiarity with legitimacy. But banks make mistakes, from making bad loans based on flawed credit models to accidentally <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cnn.com/2021/02/16/business/citibank-revlon-lawsuit-ruling/index.html">wiring nearly a billion dollars to hedge funds</a>. Retail banking customers accept slow service, arbitrary account fees, inconvenient wire cutoffs, low APYs, and other inefficiencies because that’s how things have been for a very long time. These antiquated banking processes and potential for human error are accepted as cost of doing business.</p><p>Indeed, when friends, family, coworkers, and the general public all rely on Tradfi solutions, it is taken as the “safe” default option. With so much money held by centralized institutions, the tendency to follow everyone else’s lead is powerful. With something as serious as one’s own money, the inertia to move to a new financial system is only that much greater.</p><p><strong>Trust Protocols</strong></p><p>New/potential users must trust — deeply trust — anywhere they are putting their own capital. They need assurances that the DeFi team is skilled, does not have misaligned incentives, and that it has produced secure, bug-free smart contracts. As importantly, users need to believe that others also trust in the legitimacy of the protocol.</p><p>However, trust in DeFi is both precious and elusive. New DeFi projects launch on a daily basis. Some of these are driven by generating quick profits for the team, often at the expense of its community. Malicious DeFi teams have rugged their own users.</p><p>Still, other projects, despite best efforts to conduct annual audits and implement bug bounty programs, remain subject to vulnerability and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://arxiv.org/pdf/2101.08778.pdf">hacks</a>:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/965e290b634d97ff591c8a1523491ece6798805cb74fbd0e5881d045036aaf75.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>In total, over <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://finance.yahoo.com/news/messari-defi-exploits-total-284-091600754.html">$284 million</a> has been lost to hackers since 2019.</p><p><strong>DeFi Trust Solutions</strong></p><p>Audits, insurance, and bug bounties help lend credibility to protocols. But they do not create the perception of community trust or widespread legitimacy. Further adoption among retail and institutional actors first requires the ability for anyone (technically trained or not) to be able to instantly discern how much the general public believes in a DeFi project, its team, and its code.</p><p>The Ante team has been working on a trust solution and is excited to share it with you at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ante.finance">Ante Finance</a>!</p>]]></content:encoded>
            <author>ante-finance@newsletter.paragraph.com (Ante Finance)</author>
        </item>
    </channel>
</rss>