<?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>Alex Kroeger</title>
        <link>https://paragraph.com/@alex-kroeger</link>
        <description>undefined</description>
        <lastBuildDate>Thu, 15 Oct 2026 00:50:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>Alex Kroeger</title>
            <url>https://storage.googleapis.com/papyrus_images/5140fc1b139149b92d65f580b1176f9515d8a001c20f207adab0fc612d79698f.png</url>
            <link>https://paragraph.com/@alex-kroeger</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[A modest proposal: USDC v3]]></title>
            <link>https://paragraph.com/@alex-kroeger/a-modest-proposal-usdc-v3</link>
            <guid>jykanLPr5FWPYxQKpaUJ</guid>
            <pubDate>Mon, 24 Jan 2022 15:59:22 GMT</pubDate>
            <description><![CDATA[TLDRCentre’s USDC has become the second largest stablecoin in DeFi. While it has maintained its 1:1 peg with the US dollar well, its “blacklist” functionality comes with a heavy tax on users, amounting to, by my estimate, an extra $3.6M spent in transaction fees in December 2021 alone. I propose a new version of USDC that preserves what I argue is the most salient feature of the blacklist--the ability to freeze funds--in a way that eliminates blacklist-related gas costs for users, which can b...]]></description>
            <content:encoded><![CDATA[<h3 id="h-tldr" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">TLDR</h3><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://centre.io/">Centre’s</a> USDC has become the second largest stablecoin in DeFi. While it has maintained its 1:1 peg with the US dollar well, its “blacklist” functionality comes with a heavy tax on users, amounting to, by my estimate, an extra <strong>$3.6M</strong> spent in transaction fees <em>in December 2021 alone.</em></p><p>I propose a new version of USDC that preserves what I argue is the most salient feature of the blacklist--the ability to freeze funds--in a way that eliminates blacklist-related gas costs for users, which can be found in a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/centrehq/centre-tokens/pull/338">pull request</a> to the Centre token repo.</p><h3 id="h-usd-coin-usdc" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">USD Coin (USDC)</h3><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/tx/0xe7e0fe390354509cd08c9a0168536938600ddc552b3f7cb96030ebef62e75895">Deployed in august of 2018</a>, USDC has grown to be the second largest stablecoin by market cap (next to USDT) with 44.6 billion in circulation at the time of writing. In the beginning it existed natively on Ethereum mainnet only, but has since expanded to 6 other blockchains.</p><p>USDC is managed by an organization called <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.centre.io/">Centre</a> whose founding members are <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.coinbase.com/">Coinbase</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.circle.com/en/">Circle</a>, two providers of fiat-to-cryptocurrency conversion services.</p><p>USDC has become one of the most favored stablecoins in DeFi and it’s no wonder--it has maintained its peg well and it is easily convertible 1 for 1 to dollars via Coinbase and Circle.</p><p>One area in which USDC performs poorly, however, is the cost to use it. It costs approximately <strong><em>40%</em></strong> more in network fees to transfer USDC compared to DAI, a decentralized stablecoin maintained by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://makerdao.com/en/">MakerDAO</a>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8fa355f2bdd69ab3aef44f1c1eec3218e8fc82f087d7f73aa276638a320679d9.png" alt="source: Dune Analytics." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">source: Dune Analytics.</figcaption></figure><p>Why is that? How could USDC, which implements the same ERC20 standard as DAI, cost so much more to use?</p><p>A partial explanation is that USDC is a proxy contract. This means that there is a separation between the logic of how USDC operates and the address that people interact with. This allows USDC to be upgradeable--Centre can change the logic of the contract without requiring a migration of USDC balances. However, it also requires extra steps to look up the contract where the logic is and then call it, which requires extra gas.</p><p>Another reason is that USDC costs more to use is that it has additional checks to make sure the addresses aren’t on the the <strong><em>blacklist</em></strong>. USDC allows an admin to bar specified addresses from interacting with USDC.</p><p>When the <code>transfer</code> function on USDC is called, the contract checks that both the sender and receiver aren’t on this naughty list. According to the Centre <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://f.hubspotusercontent30.net/hubfs/9304636/PDF/centre-whitepaper.pdf">whitepaper</a>, this blacklist is meant to protect users as well as maintain regulatory compliance.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/55d752817fa1be620974ded2faa2d7545079d8bbea74708762023b80746fb4e9.png" alt="When \`transfer\` is called, the contract checks that both the sender (\`msg.sender\`) and the receiver (\`to\`) are not on the blacklist." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">When \`transfer\` is called, the contract checks that both the sender (\`msg.sender\`) and the receiver (\`to\`) are not on the blacklist.</figcaption></figure><p>Unfortunately for users, however, checking the blacklist comes at a cost. Each check of the blacklist costs ~2100 gas or around $0.63 a pop (see the appendix for why this is). To transfer, this list is checked twice, adding ~$1.26 to the transaction.</p><p>Calling <code>transferFrom</code> (the call used when interacting with other contracts like Uniswap) requires 3 checks of the blacklist, for a total cost of up to ~6300 gas, or ~$1.89.</p><p>These costs add up. I estimate that in December 2021 alone, these blacklist checks added about <strong>$3.6M</strong> in gas fees for USDC users.</p><h3 id="h-slimming-down-blacklist-functionality" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Slimming Down Blacklist Functionality</h3><p>I would argue the ability to freeze funds is the only aspect of the blacklist that is worth saving. I discuss this in the context of the two stated aims of the blacklist according to Centre: regulatory compliance and protecting users.</p><h4 id="h-regulatory-compliancestopping-the-bad-guys" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Regulatory Compliance/Stopping the Bad Guys</h4><p>When an address is added to the USDC blacklist, they can no longer interact with USDC directly--it can’t receive funds nor can it move funds.</p><p>If the address has an existing balance, the entity behind that address now can’t access it--that’s a real cost. However, in terms of preventing future interaction with the USDC contract, the blacklist isn’t all that binding.</p><p>Say you’re the owner of an address that gets blacklisted. If you want to continue to use USDC, you have a two options:</p><ol><li><p>You could derive a new Ethereum address in your wallet (for free) and continue using USDC.</p></li><li><p>You could create a proxy contract wallet from your address, for instance a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gnosis-safe.io/#getting-started">Gnosis Safe</a> contract, and interact with USDC via that contract. The USDC blacklist contains your normal address, not the contract.</p></li></ol><p>You would probably opt for 1, as it is easy and bears less risk for additional blacklisting, but the point is the blacklist is not a useful tool for stopping the <em>entity</em> behind an address from interacting with USDC. It’s a measure that is more theater than substance.</p><p>The logic is similar for contracts. You could blacklist a particular project’s contract, but contracts can be re-deployed.</p><p>The risk that bad actors are most likely concerned about is having their USDC frozen. If you lock their balance, that’s a real economic hit for which they have no recourse. If an actor with a frozen balance for some reason continues to use USDC and acquires a fresh balance, Centre could freeze the additional funds. This could even be done in an automated way.</p><p>Simply freezing balances doesn’t require an approach as heavy-handed as the blacklist, however, which I’ll discuss later in this post.</p><h4 id="h-protecting-users" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Protecting Users</h4><p>The blacklist does effectively protect users from addresses that are determined to steal users’ funds--for example, scam accounts.</p><p>However, doing this at the smart contract level is <em>the most expensive place to do this</em> (i.e. $3.6M per month expensive)<em>.</em> Building warnings into wallets is a much cheaper place to help protect users from errant behavior or interacting with scam accounts, and they’re even more effective in that they can help prevent the user from spending gas on a failed transaction.</p><p>Freezing funds also still leaves recourse for users--in theory you can freeze USDC at a scam address, thereby taking that USDC out of circulation, and Centre wanted to do so, they could mint USDC for the affected users to replace that removed USDC.</p><h3 id="h-freezebalance" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">freezeBalance</h3><p>In the previous section I argue that freezing funds is the sole aspect of the blacklist worth saving (or at least worth spending transaction fees on).</p><p>In my proposed USDC v3, I remove the blacklist checks from all transfer and approval functions. This would save the gas spent on these checks (the $3.6M in cost).</p><p>In its place, I introduce a new function called <code>freezeBalance</code>. This function allows an admin (in this case, an address that is already given the role of blacklister) to freeze an account’s funds.</p><p>Under the hood, this sets the target account’s balance to zero, removes that amount from the total supply, and updates a separate account mapping (<code>frozenBalances</code>) to reflect the funds that are frozen. <code>frozenBalances</code> makes accounting for these actions easier as well as allows the admin to unfreeze balances (calling <code>unfreezeBalance</code>) if the initial freeze is later deemed to have been done in error.</p><h3 id="h-concluding-thoughts" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Concluding thoughts</h3><p>My ultimate hope is that my proposed version of USDC gets adopted to save users money as well as make a (very) modest dent in Ethereum’s congestion problem by reducing USDC’s footprint in Ethereum blocks.</p><p>This code for can be in a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/centrehq/centre-tokens/pull/338/files">pull request</a> to Centre’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/centrehq/centre-tokens">tokens repo</a>.</p><p>In the high gas environment that we’ve experienced on Ethereum mainnet the past two years, it’s crucial for projects behind heavily-used contracts to scrutinize gas usage very carefully.</p><h3 id="h-appendix" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Appendix</h3><h4 id="h-acknowledgements" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Acknowledgements :)</h4><p>Thanks to Noah Zinsmeister, Kelsey Dean, and Daniel Pyrathon for reviewing this post.</p><h4 id="h-blacklist-gas-costs" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Blacklist Gas Costs</h4><p>The most significant (though not the only) gas costs associated with checking the blacklist is the fact that it needs to read from storage (specifically looking up an address in a mapping of address to a boolean value of whether that address is blacklisted).</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5deca70b5fe7b965ce6cea1d2aa99f847e2689bf07a9df7972a3b2e90ded83db.png" alt="Centre&apos;s Blacklistable contract allocates storage for a mapping of address to a boolean." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Centre&apos;s Blacklistable contract allocates storage for a mapping of address to a boolean.</figcaption></figure><p>The cost of every action one can take in the EVM is specified in the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.github.io/yellowpaper/paper.pdf">Ethereum yellow paper</a>. This document is updated as hard forks modify the behavior of the EVM. The relevant costs for storage access were last updated in the April 2021 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.ethereum.org/2021/03/08/ethereum-berlin-upgrade-announcement/">Berlin hardfork</a> due to the inclusion of <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-2929">EIP 2929</a>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9093ab7f9f32c23811a56efc5d91b5ada680b449c0cf8fef3bd6e22394450b3f.png" alt="Storage access costs from the Ethereum yellow paper." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Storage access costs from the Ethereum yellow paper.</figcaption></figure><p>The cost for a “cold sload” (“cold” meaning the storage slot has not yet been accessed in the transaction) is 2100 gas. Once a storage slot has been accessed, the cost for any subsequent access within that transaction is 100 gas.</p><p>As discussed previously, the USDC blacklist is checked twice for each <code>transfer</code>--once for the sender and once for the receiver--and three times for each <code>transferFrom</code>once for the receiver--once for the address calling <code>transferFrom</code> (typically a contract), once for the sender, and once for the receiver.</p><p>In theory some of these addresses within a <code>transfer</code>/<code>transferFrom</code> could be duplicates, in which case the additional read would cost only 100 gas. In practice, however, these addresses (sender, receiver, caller) will often all be different addresses, so each read will cost 2100 gas.</p><p>To put this into context, 2100 gas at $3K ETH and 100 gwei gas price costs $0.63. This may sound low, but add multiple checks per transaction and millions of transactions, the costs add up.</p><h4 id="h-blacklist-checks-for-approve" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Blacklist Checks for Approve</h4><p>In addition to <code>transfer</code> and <code>transferFrom</code>, there are two checks of the blacklist for <code>approve</code>. The<code>approve</code> allows a separate address (say the Uniswap router or a Compound cToken contract) to spend your balance (subject to the logic of the contract, of course).</p><p>USDC checks that the address granting the approval (<code>msg.sender</code>) and the address that is being granted the approval (<code>spender</code>) are not on the blacklist.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1b96a16e438d6490d8e362cc06d9df4227eff56ec9e28264f9598c069add599a.png" alt="The USDC \`approve\` function." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">The USDC \`approve\` function.</figcaption></figure><p>While in this post I argue that the most important functionality of the blacklist can be preserved while getting rid of the blacklist checks on <code>transfer</code> and <code>transferFrom</code>, the blacklist checks on <code>approve</code> are particularly superfluous, since even if approval is granted from or to a blacklisted address, the checks on <code>transfer</code> and <code>transferFrom</code> prevent any movement of funds.</p><p>These blacklist checks for <code>approve</code> impose a cost on all users calling this function and should be removed. Blacklist checks for <code>approve</code> alone cost users <strong>$346K</strong> in December 2021, though I note that December had a higher number of approvals than normal due to token mining with a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://0x7B1AAF21AC0D420666B5966338FF9aEe763C29DF">Gearbox Protocol contract</a> on December 16 (see <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/370753">Dune query</a>). Excluding these the Gearbox approvals, the <code>approve</code> blacklist checks cost users ~$209K.</p><h4 id="h-source-for-data-analysis" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Source for Data Analysis</h4><p>I used <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/home">Dune Analytics</a> for data analysis mentioned in this post.</p><p>You can find the source for the cost of DAI/USDC transfers in the following queries:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/352583">DAI</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/352483">USDC</a></p></li></ul><p>For the numbers mentioned in the post, I calculated the median gas cost of a simple transfer transaction from the last week of 2021.</p><p>I calculated the USD value of the excess ETH spent on blacklist lookups in December 2021 relative to my proposed implementation in the following <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/346258">query</a>.</p><p>To make the calculations tractable without timing out, I calculated the excess ETH for <code>approve</code>, <code>transfer</code>, and <code>transferFrom</code> in separate queries and stored the results in tables. The queries for these tables can be found linked in the query above.</p><p>I calculate the gas spent on <code>SLOAD</code> related to the blacklist, taking into account the lower cost of warm access if an address is repeated.</p><h4 id="h-additional-implementation-details" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Additional Implementation Details</h4><p>When deploying v3, addresses on the blacklist with frozen balances would be able to move this balance if they aren’t frozen via <code>freezeBalance</code>, so it’s imperative that the deployment transaction includes this step.</p><p>I left blacklist checks on the <code>mint</code> functions, since they are not very frequent called and those functions only affect Centre’s costs, not the costs of USDC users.</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0"></h4>]]></content:encoded>
            <author>alex-kroeger@newsletter.paragraph.com (Alex Kroeger)</author>
        </item>
        <item>
            <title><![CDATA[DAOs and the Free-rider Problem]]></title>
            <link>https://paragraph.com/@alex-kroeger/daos-and-the-free-rider-problem</link>
            <guid>XUvPlNwxGvr5lNVw8w2J</guid>
            <pubDate>Tue, 21 Dec 2021 16:39:05 GMT</pubDate>
            <description><![CDATA[The free-rider problem arises when a good or service has private costs and non-excludable public benefits. A classic example is a firework show. Fireworks can be enjoyed by anyone in a particular area regardless of whether they pay for it (it’s hard to stop people from looking at the sky if they don’t have a ticket). Lots of folks may want the firework show, but there’s not enough economic incentive to go through the effort and cost of arranging it if you only reap the private benefit (the en...]]></description>
            <content:encoded><![CDATA[<p>The free-rider problem arises when a good or service has private costs and non-excludable public benefits. A classic example is a firework show. Fireworks can be enjoyed by anyone in a particular area regardless of whether they pay for it (it’s hard to stop people from looking at the sky if they don’t have a ticket).</p><p>Lots of folks may want the firework show, but there’s not enough economic incentive to go through the effort and cost of arranging it if you only reap the <em>private benefit</em> (the enjoyment of getting to watch the fireworks yourself) and don’t reap some of the <em>public benefit</em> (everyone else’s enjoyment of the fireworks).</p><h2 id="h-dao-governance-free-riders" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">DAO Governance free riders</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2a94f1b246c10bf1fde08f901e35fdf99a44c614b417102aa4bcf119423b61d5.png" alt="Source: Robert Leighton (artist) and The New Yorker, https://www.newyorker.com/cartoon/a17032." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Source: Robert Leighton (artist) and The New Yorker, https://www.newyorker.com/cartoon/a17032.</figcaption></figure><p>In DAOs, all token holders benefit from good governance whether they participate in it (create proposals, vote on proposals) or not.</p><p>Ultimately, this doesn’t matter much as long as good governance takes place, but I am not one to rely on the goodwill of some to do work for an entire group--anyone who has suffered through a group project in school can attest that this does not always lead to desirable outcomes.</p><p>Furthermore, the current state of affairs can have a centralizing effect--you’re incentivized to participate if your private benefit is a significant chunk of the group benefit, i.e. in the case of DAOs, you own a large percentage of the tokens.</p><h2 id="h-incentivizing-governance-participation" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Incentivizing governance participation</h2><p>What if we privatize some of the benefits of governance participation?</p><p>I say we pay people to participate in governance. Those who participate should be rewarded with a greater stake in the protocol. From another perspective, we should be <em>punishing</em> those that don’t participate in governance with dilution of their stake in the protocol.</p><p>There are two primary activities in on-chain governance--creating proposals and voting on proposals.</p><p>Creating proposals is hard work, and should be rewarded through bounties, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.unigrants.org/">one-off grants</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://compound.finance/governance/proposals/51">streaming contributor grants</a>, and one-off payments baked into proposals. Proposals are not created equally in terms of their difficulty and impact (a parameter update is much simpler and typically less impactful than rewriting a contract).</p><p>While I think it’s important to incentivize the creation of good proposals, I don’t think there should be a one size fits all solution.</p><p>Voting, on the other hand, merits a more formalized approach. Among all the DAOs I’ve seen, voting is not explicitly incentivized, and so non-voters free-ride on the diligence of voters. I think voting should come with an explicit reward of more governance tokens in proportion to one’s voting balance.</p><p>I discuss some potential incentive misalignments with voting rewards and how to address them below.</p><h3 id="h-casting-uninformed-votes" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Casting uninformed votes</h3><p>One way to game voting incentives would be to simply vote (either always “yes,” always “no,” or randomly) on every proposal to earn rewards regardless of the proposal. This isn’t even hypothetical at this point as, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/transmissions11">@transmissions11</a> implemented a lovely <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0xf299d8d1cb7b3636083c732c67dc399dbb05e625">contract</a> that only allows you to vote no on every proposal.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/transmissions11/status/1465907960765321220">https://twitter.com/transmissions11/status/1465907960765321220</a></p><p>My solution here is to provide substantially higher rewards for votes that end up winning. This encourages token holders to vote the best option and incentives folks to try to persuade others to their viewpoint as well.</p><h3 id="h-voting-with-the-majority-near-the-end-of-the-voting-period" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Voting with the majority near the end of the voting period</h3><p>Another type of free rider voter could simply wait until the voting period is near complete and vote at the end once the outcome seems assured.</p><p>My solution here is to have a reward decay schedule. The voting reward should be highest at the beginning of the vote period and decay to zero at the end. This encourages token holders to stay on top of upcoming votes and diligence the proposal before the voting period begins.</p><h3 id="h-spamming-nonsense-proposals" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Spamming nonsense proposals</h3><p>Another potential way to game voting rewards is to create useless proposals and vote on them.</p><p>However, many DeFi protocols, including Uniswap and Compound, have some degree of spam prevention built in--the proposer must meet a minimum threshold of delegated voting power. Although incomplete, one solution to this problem is to exclude the proposer (and thus their delegated voting power) from voting rewards.</p><p>If it becomes an issue, the vote threshold can be raised to discourage this type of behavior.</p><h2 id="h-a-renaissance-in-delegation" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">A Renaissance in Delegation</h2><p>Direct voting is not for everyone. In my opinion, it’s difficult to be informed enough about more than 2 or 3 protocols to be an active participant, and that’s assuming that you have the ability to dedicate a significant amount of time to DeFi governance (and I’ve been told that most people, unlike me, have a life outside of crypto).</p><p>For many DAO token holders, delegation to an active community member makes the most sense. The beauty of voting incentives is that it makes being a delegate not just a labor of love, but a potential occupation.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/943cd30aa1dc42137f6e6716468e4b54bfd2c782ca10c558aac1e250213315f9.png" alt="Delegation advertisement coming soon to your local periodical. Generated using fodey.com" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Delegation advertisement coming soon to your local periodical. Generated using fodey.com</figcaption></figure><p>By default voting rewards would accrue to the address that voted, i.e. delegates would get rewarded not only for their own voting power but the voting power of everyone who delegated to them.</p><p>While this is great for the delegate, it doesn’t leave much incentive to delegate your tokens. It&apos;s easy to imagine delegation contracts that allow delegates to return a percentage of rewards back to the delegators. Delegates would compete along two dimensions:</p><ol><li><p>how good of a delegate they are (high vote participation, good reputation, sound judgment, etc.)</p></li><li><p>what percent of rewards they return to delegators</p></li></ol><h2 id="h-concluding-thoughts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Concluding thoughts</h2><p>DAOs (and web3 in general) offer a rich design space to create incentive schemes that allow us to build better applications. The current DAO voting model, however, is uninspired from an incentive perspective.</p><p>Voting rewards can better incentivize good governance and create a competitive market for delegation.</p>]]></content:encoded>
            <author>alex-kroeger@newsletter.paragraph.com (Alex Kroeger)</author>
        </item>
        <item>
            <title><![CDATA[Should Uniswap be an oracle protocol? Always has been.]]></title>
            <link>https://paragraph.com/@alex-kroeger/should-uniswap-be-an-oracle-protocol-always-has-been</link>
            <guid>A6ztGjo3eew0jL7BNNRa</guid>
            <pubDate>Mon, 06 Dec 2021 16:55:02 GMT</pubDate>
            <description><![CDATA[In May of this year, Vitalik created a post on the Uniswap governance forum called, “UNI should become an oracle token.” He argues that there is a need for oracles to provide off-chain data, and that UNI is in a good position to provide an alternative to Chainlink for high-value, latency-tolerant use cases. While it’s an interesting idea, as I reflected on that post recently, I was thinking about how Uniswap already is an oracle protocol. It already provides a price feed from the largest DEX ...]]></description>
            <content:encoded><![CDATA[<p>In May of this year, Vitalik created a post on the Uniswap governance forum called, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gov.uniswap.org/t/uni-should-become-an-oracle-token/11988">“UNI should become an oracle token.”</a> He argues that there is a need for oracles to provide off-chain data, and that UNI is in a good position to provide an alternative to Chainlink for high-value, latency-tolerant use cases.</p><p>While it’s an interesting idea, as I reflected on that post recently, I was thinking about how Uniswap <em>already is</em> an oracle protocol. It already provides a price feed from the largest DEX on Ethereum. UNI already is an oracle token, the UNI DAO just hasn’t done much with that fact, as of yet at least.</p><h3 id="h-a-history-of-uniswap-as-an-oracle" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">A history of Uniswap as an oracle</h3><p>Ever since v1, Uniswap has been an oracle protocol, albeit a very crude one at the time. Uniswap v1 was a series of ETH-ERC20 pools with a simple <code>x * y = k</code> pricing mechanism. You could query for the values of the ETH and the respective ERC20 token in any pool, and viola, you have a spot price oracle.</p><p>v1 leaves a lot to be desired as an oracle protocol, however. First, everything was priced in ETH. In order to get a non-ETH quote, say the price of BAT in terms of USDC, you would need to chain prices together (in this case, BAT-ETH and ETH-USDC).</p><p>Second, the price was a simple point-in-time (and more specifically and tragically, point-in-a-block) spot price. This is vulnerable to manipulation, as an “unfortunately timed” liquidity withdrawal and large trade could swing the price dramatically. I wouldn’t recommend relying on that price for a sensitive task like determining if a borrow position is underwater.</p><p>v2 improved on the utility of Uniswap as an oracle. First, v2 allowed for any arbitrary ERC20-ERC20 pair. Second, each pool took a snapshot of the price at the beginning block before any trade or liquidity change had taken place, which made manipulation more difficult. Finally, the price value it stored (a running accumulator of the price multiplied by the seconds since the last block) allowed a user to calculate a time-weighted average price (TWAP) as opposed to a simple spot price.</p><p>Getting a TWAP from a v2 pool did not work out of the box, however--it required integrators to store past values of the running accumulator in a separate contract for calculation.</p><p>Uniswap v3 maintains the benefits offered in v2, but also addresses the aforementioned flaw by offering the ability to store a series of accumulator values (only 1 value is stored by default, but anyone willing to pay the gas cost can expand the number of tracked values to a maximum of 65,535 observations, or ~9 days of prices).</p><h3 id="h-oracle-usage-today" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Oracle usage today</h3><p>Uniswap v3 is already being used as an on-chain oracle in varied contexts.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/278991">A number of projects</a> call Uniswap v3’s oracle function from their contracts, including:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://popsicle.finance/">Popsicle Finance</a> (an LP yield optimization protocol)</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://keep3r.network/">keep3r network</a> (a decentralized task runner protocol)</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://frax.finance/">Frax</a> (an algo stablecoin)</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://lixir.finance/">Lixir Finance</a> (an LP manager for Uniswap v3)</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rari.capital/">Rari Capital</a> (creator of the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://app.rari.capital/fuse">Fuse lending protocol</a>)</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.babylon.finance/">Babylon Finance</a> (decentralized asset management)</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://unipilot.io/">Unipilot</a> (an LP yield optimization protocol)</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.angle.money/">Angle</a> (a stablecoin protocol)</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f234edead18b4564e255b01b07a57c0ee1f2e97d7abfcb637a26e22e796257e4.png" alt="Source: Dune Analytics" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Source: Dune Analytics</figcaption></figure><p>These oracle calls are made across a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/277692">wide variety of pairs</a>. We can see in the figure below that while USDC-WETH is the most commonly called pair, it only comprises 17% of oracle calls. There is a long tail of assets for which the oracle functionality is used. A number of these are directly related to the protocols mentioned above (.e.g FRAX, KP3R). More, however, are simply assets for which Uniswap is likely one of the most significant sources of liquidity (e.g. ENS and of course ELON).</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/50465dbdcb70379681ea31c9ee53555d085fccceb51d43bd3b714e3eb5bbcdd4.png" alt="Source: Dune Analytics" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Source: Dune Analytics</figcaption></figure><h3 id="h-uniswap-dao-as-keeper-of-the-oracles" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Uniswap DAO as keeper of the oracles</h3><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/41e5b31b1bb56231a0a5a03c06852a9532899e9b03727e6af5230fe1471180b4.jpg" alt="Priests who worked with the oracle at Delphi would receive her utterances and disseminate the answer to the petitioner." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Priests who worked with the oracle at Delphi would receive her utterances and disseminate the answer to the petitioner.</figcaption></figure><p>The oracle functionality is already being used, and that’s despite a relative dearth of material on the the performance of Uniswap oracles (though I refer you to an <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/euler_mab/status/1459314402059034634?s=20">excellent thread</a> on the cost of attacking a v3 oracle by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/euler_mab">Michael Bentley</a>).</p><p>Where is the incentive to improve and maintain the oracle experience, however? Oracle usage doesn’t currently benefit traders, LPs, or maintainers of the protocol.</p><p>Protocol trading fees are already a possible source of DAO cash flows in <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/Uniswap/v2-core/blob/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc/contracts/UniswapV2Pair.sol#L91">v2</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/Uniswap/v3-core/blob/62d65bf88c4fb23671104c28f5bcae566274cb15/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol#L10">v3</a> (though no fees have been collected to date).</p><p>It’s worth considering a fee to use price oracles. While this would require some protocol changes, this could be implemented as a flat fee in ETH per call or a registration of a project’s contract on an array of approved oracle callers.</p><p>In exchange for these fees, the Uniswap DAO could become a “keeper of the oracles.” What would that mean in practice? The DAO could:</p><ul><li><p>act as a “liquidity provider of last resort”</p></li><li><p>provide liquidity incentives to pools that are high value as price oracles</p></li><li><p>provide data and research regarding oracle performance</p></li><li><p>provide better documentation for best practices around oracle usage</p></li></ul><p>By “liquidity provider of last resort,” I mean the DAO could create an automated strategy or appoint an LP manager to provide certain amount of passive liquidity to pools that are important oracles and running low on liquidity. This could dissuade attacks as well as respond to attacks spanning multiple blocks that involve withdrawing liquidity or affecting the liquidity balance of a pool.</p><h3 id="h-the-limitations-of-current-uniswap-oracles" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The limitations of current Uniswap oracles</h3><p>This discussion feels incomplete without acknowledging some of the limitations of the using Uniswap oracles as they exist today.</p><p>While using a simple spot price (as opposed to a TWAP) from an AMM is inadvisable, a TWAP reduces the freshness of your data (it adapts more slowly to changing market conditions by definition). In choosing the length of time over which to measure the TWAP, you face a dilemma:</p><ul><li><p>The shorter the time window, the more the TWAP is susceptible to manipulation.</p></li><li><p>The longer the time window, the slower the TWAP adjusts to changing market prices.</p></li></ul><p>Take a lending protocol for example. If the price of collateral hits a sudden downtrend, and the TWAP doesn’t reflect that a position is under-collateralized until 30 minutes after the start of the downtrend, the spot price by then may be even lower, which could cause the protocol to take a loss on the now possibly underwater position.</p><p>That being said, the attractive part of Uniswap oracles is they work relatively autonomously. Even without the extra assurances a DAO could provide, they would continue to work well just given the incentives of market participants.</p><p>Coming full circle back to Vitalik’s post, it could be interesting to explore how the DAO could use current pool TWAP model as one ingredient in an oracle solution that adds in fresher, off-chain sources of price data. Until then, I say a bird in the hand is worth <code>getTWAP(birdsInBush, birdsInHand, ‘30 minutes’)</code> in the bush.</p><h3 id="h-appendix" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Appendix</h3><p>Image of the oracle at Delphi is ‘The Oracle’ by Camillo Miola (1880), source: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://media.getty.edu/museum/images/web/enlarge/00070801.jpg">Getty</a>.</p><p>Dune analytics queries:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/277656">Uniswap v3 oracle calls by project, by project, past 28 days from 2021-12-04</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/278991">Uniswap v3 oracle calls by pair, past 28 days from 2021-12-04</a></p></li></ul>]]></content:encoded>
            <author>alex-kroeger@newsletter.paragraph.com (Alex Kroeger)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/f7220d55ee7a692cbe240540ed52f2bf65e49098e21ce5a23babdbc839b96b35.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[The US government as a smart contract]]></title>
            <link>https://paragraph.com/@alex-kroeger/the-us-government-as-a-smart-contract</link>
            <guid>xD9opmdHeW64NZumyWRs</guid>
            <pubDate>Tue, 30 Nov 2021 17:23:12 GMT</pubDate>
            <description><![CDATA[A technical guide to on-chain governanceDisclaimer: this post and accompanying code is meant for educational purposes only. None of this is audited, and you should seek out audits before using contracts in production. There has been much ado about DAOs lately--they are being used to govern financial protocols, form modern day guilds, and crowdfund the sale of historical documents. But how do they work on-chain? This post will walk through an example of setting up governance using a variant of...]]></description>
            <content:encoded><![CDATA[<h1 id="h-a-technical-guide-to-on-chain-governance" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">A technical guide to on-chain governance</h1><p><em>Disclaimer: this post and accompanying code is meant for educational purposes only. None of this is audited, and you should seek out audits before using contracts in production.</em></p><p>There has been much ado about DAOs lately--they are being used to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://vote.makerdao.com/">govern financial protocols</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/developer_dao">form modern day guilds</a>, and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/ConstitutionDAO">crowdfund the sale of historical documents</a>.</p><p>But how do they work on-chain? This post will walk through an example of setting up governance using a variant of the popular governance contracts created by Compound Finance. The task? Deploying the U.S. federal government as smart contracts on Ethereum.</p><p>All the code discussed in this post can be found in a GitHub repo <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/alexkroeger/the-federal-govt-as-solidity/tree/main">here</a>. Hat tip to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://openzeppelin.com/">OpenZeppelin</a> for an excellent and extensive <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/OpenZeppelin/openzeppelin-contracts">library of contracts</a> that I use heavily in this tutorial.</p><h2 id="h-the-contracts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The contracts</h2><h3 id="h-congresstoken" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">CongressToken</h3><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/contracts/CongressToken.sol">link to file</a></p><p>The first step in on-chain governance is for determining who will be doing the governing! For the federal government, that will be Congress.</p><p>DAO voting power is typically determined by one’s balance of an <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/developers/docs/standards/tokens/erc-20/">ERC20 token</a>. To create our governance token, which I’ll be calling <code>CongressToken</code>, we’ll use OpenZeppelin’s standard ERC20 implementation as well as an extension they’ve made called <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Votes.sol">ERC20Votes</a>.</p><p><code>ERC20Votes</code> will give us the ability to keep track of voting power and exposes an interface to delegate the voting power of your tokens to yourself or someone else.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9803739cb087f09a547b4a1b3eecbabec4bef3e11aaf78fb5859358dea5132a1.png" alt="CongressToken" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">CongressToken</figcaption></figure><p>Two items to note here. First, in the constructor, I mint 3 tokens (technically there should be 535, one for each member of Congress, but I’m too lazy to simulate more than 3 members) and transfer them to the deployer address.</p><p><code>_mint(msg.sender, 3);</code></p><p>Since there is no publicly available <code>mint()</code> function, this will be the total supply of CONGRESS forever. I leave it up to the deployer to distribute these tokens, which is not what you want to do in prod. It would be more appropriate to grant the tokens to a separate contract that will distribute tokens according to some rule.</p><p>Second item to note is that I set <code>decimals()</code> to 0. Token balances are always stored as an integer on-chain, and the ERC20 standard dictates that you specify the number of decimal places used to convert these integers into the desired fractional units. 18 decimals is most common, as that is used by ether itself. Here, I don’t desire any ability to fractionalize votes (it’ll be one senator, one vote), so I set decimals to 0.</p><h3 id="h-federalgovernment" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">FederalGovernment</h3><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/contracts/FederalGovernment.sol">link to file</a></p><p>Next we need to create the logic for governance--how do proposals get created and voted on?</p><p>For this we use the OpenZeppelin <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/Governor.sol">Governor</a> contract. It’s based on the popular Compound governance contracts, which are also used by Uniswap. Additionally, OpenZeppelin has made an extension called <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/compatibility/GovernorCompatibilityBravo.sol">GovernorCompatabilityBravo</a>, which can make the interface of the governance contract compatible with Compound’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorBravoDelegate.sol">GovernorBravo</a>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cdbc5103939cec75a76f3a999ae249ec13caeaca121f9b3799633297498db9a1.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>There are two constructor arguments--the first (<code>_token</code>) is an <code>ERCVotes</code>-compatible ERC20 that will serve as the governance token. For my setup this will be the address of <code>CongressToken</code>. The second (<code>_timelock</code>) is address of a timelock contract, which we’ll get to shortly.</p><p>I set a few constants in the contract. <code>GovernorVotesQuorumFraction</code> controls what percent of the total supply of the governance token needs to vote in order for a proposal to pass. I (somewhat arbitrarily) have 4%.</p><p><code>GovernorVotesQuorumFraction(4)</code></p><p>The <code>votingDelay</code> is the amount of time between when a proposal is created and when voting begins, specified in terms of number of blocks. This gives governance token holders time to review the proposal and delegate their voting power if they choose to do so. I set this at a low value (2 blocks), but this should probably be a day or two in production systems.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/831a1b9d0d882ba371bac6224c914ba6e08782c77ac59857338d64ca6f2e213f.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 <code>votingPeriod</code> is the amount of time allocated for voting in terms of number of blocks. Addresses with delegated voting power would need to submit an on-chain vote transaction during that amount of time. I again set this to a low value (100 blocks), but this should be probably 3-5 days in a production system for sensitive items.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/15926f6d9e98a7a43afad1435b0a997aadde5f7cc00651bb97b53963850765e5.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>Finally, I set the <code>proposalThreshold</code>. This ensures that not just anyone can submit a proposal--you need to have a certain amount of delegated voting power. Here, I choose 1, meaning any member of congress (delegated CONGRESS voting power of 1) can submit a proposal.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/70e15cecec47b6c83ff2046b19ce9ec6e31a218995ac80993a9f3ced25ebc078.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><h3 id="h-federalgovernmenttimelock" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">FederalGovernmentTimelock</h3><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/contracts/FederalGovernmentTimelock.sol">link to file</a></p><p>Many DeFi protocol governance systems include a timelock contract. This contract is the one that has the ability to update critical systems, and ensures that no changes can be made without some delay that allows affected users to withdraw funds, change parameters, etc. before a change is made.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fba5f61c085bc91375b2efcae329e1aad3633c2ded03b7f636ed410378857d0b.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>For this contract I simply use OpenZeppelin’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/TimelockController.sol">TimelockController</a>, which has 3 constructor arguments. The first, <code>_minDelay</code>, specifies the amount of time (in seconds this time) that must pass before a change is put into effect. The second and third are arrays of addresses having to do with who can affect changes. <code>_proposers</code> can queue a change and <code>_executors</code> can enact the change.</p><p>We’ll get into how to set those values when we get into the deployment.</p><h3 id="h-usdollar" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">USDollar</h3><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/contracts/USDollar.sol">link to file</a></p><p>Every governance system needs something to govern!</p><p>In this setup, the federal government manages an ERC20 contract representing the US Dollar.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f11087d3c77e0e7a0e66470a126efea3021940e8afeda5a8ef46475b98deeb9c.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>I again use OpenZeppelin’s standard ERC20 implementation, but I don’t use the <code>ERC20Votes</code> extension, because USD won’t be a governance token. I make use of OpenZeppelin’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol">Ownable</a> contract.</p><p><code>Ownable</code> allows you to restrict certain functions to be used by an admin only. The default owner is the contract deployer. In the constructor, I add an argument to specify the owner to override the default behavior. I’ll make the timelock contract the owner during deployment.</p><p>I add two public functions here, <code>mint</code> and <code>burn</code>, that have the modifier <code>onlyOwner</code>. This will give the federal government the ability to mint and burn USD by proposal.</p><p>Generally, governance should have the ability to call certain admin functions (like <code>mint</code> and <code>burn</code> in this case).</p><h2 id="h-deployment" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Deployment</h2><p>In the accompanying repo, I include a script called <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/scripts/deploy_util.ts">deploy_util</a> that sets up the governance system.</p><p>The first step is to deploy the governance token:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/98489b9ea4fc92299365713a7360332285f0d89a1859fb881c1279f4bdd84563.png" alt="deploying CongressToken." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">deploying CongressToken.</figcaption></figure><p>This is straightforward--I print out the deployed address along with decimals and total supply.</p><p>Next step is to deploy the timelock contract, as it will be an input argument for the governance contract.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d57910f50e9dbc3994990960afc3e29093ef2497dcf2110ce504234f559cd96f.png" alt="deploying the timelock contract" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">deploying the timelock contract</figcaption></figure><p>Note that I leave <code>_proposers</code> empty here. The governance contract will be the only proposer, but we do not yet know its address. For <code>_executors</code>, I include only the zero address (0x000…) which means any address can execute. This isn’t insecure, since only transactions that are proposed can be executed, and only governance can propose.</p><p>Next I deploy the governor contract, passing in the addresses for the governance token and the timelock.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/84d1c826d383e8b6a59b75b364dd8b37176aaa450e6fd2953f18d0df81bc2105.png" alt="deploying the governor contract" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">deploying the governor contract</figcaption></figure><p>At this point the deployer address is an admin on the timelock. I grant the <code>FederalGovernment</code> contract the role of proposer, and then renounce the deployer’s admin privilege on the timelock so that governance is in control.</p><p>Finally, I deploy the <code>USDollar</code> contract, passing in the timelock contract as the owner. With that, we’re ready for governance!</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/317bc8f2c7b5e1af894522297c6df7e6bde6509cbc8891a125264f7d7818a626.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-creating-and-executing-a-proposal" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Creating and executing a proposal</h2><p>Now we can see what the governance system can do.</p><p>The repo contains another script called <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/scripts/proposal_scenario.ts">proposal_scenario</a> that walks through the creation of a proposal in a local hardhat environment.</p><p>First, some housekeeping. I need to distribute the CONGRESS tokens to some senators. I grab three spare addresses to have 3 senators (<code>redSenator</code>, <code>blueSenator</code>, and <code>swingSenator</code>--think Joe Manchin). In order to vote later, the token balances must be delegated to a voter. In this case, all the senators delegate to themselves.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/bc92408107b224daf96c508be2fc20c8c61974164a732bb8fc7f97174acc4e88.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>Now we’re ready to create a proposal.</p><h3 id="h-creating-a-proposal" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Creating a proposal</h3><p><code>redSenator</code> wants to propose that $2M is minted, and $1M goes to them and $1M goes to <code>swingSenator</code>.</p><p>The <code>FederalGovernment</code> contract interface has a <code>propose</code> function, whereby you can pass calldata to be executed by the timelock.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cce28ef515ce751f82200ecf759dc3e6e7f5584dead7a9f12ee1f9cd88f4cd54.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>I create the calldata for the 2 calls to mint on the USDollar contract, and add them to the proposal. The proposal also needs the address to call for each calldata (the USDollar contract for both in this case), the amount of ETH to be sent with the call (0 in this case), and a description.</p><p>Once we create the proposal, the governance contract recognizes it as “pending.”</p><h3 id="h-voting" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Voting</h3><p>We can’t quite vote on the proposal yet. You might remember that I set <code>reviewPeriod</code> value on the governance contract that requires <code>n</code> blocks pass before voting begins, giving folks a chance to delegate if they choose to do so.</p><p>Since this is a local environment, we can speed through it.</p><p>Now the senators can vote. Given that they’ll receive $1M each, <code>redSenator</code> and <code>swingSenator</code> are strongly in favor. <code>blueSenator</code>, who will receive nothing, opposes.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/919d780181731ca9e04cf82b153ecc0644537ef1f948744da507b32dd01ba75e.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>If we call the governance contract, we can see the votes recorded.</p><h3 id="h-queuing-the-proposal" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Queuing the proposal</h3><p>Before we can queue up the proposal with the timelock, the voting period must finish. You may recall that I set this to 100 blocks in the governance contract.</p><p>Once again, we speed through. Since the yeas have it, the proposal is in the “succeeded” state.</p><p>The next step is to queue the proposal with the timelock. The governance contract allows anyone to do this once the voting process is done, so I have <code>swingSenator</code> do the honors.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cd232aa70d1cbc0e487edc79093e47dfce504ac7f3eb224c60abf64615ae1018.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><h3 id="h-executing-the-proposal" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Executing the proposal</h3><p>The final step is to go live with the changes. We have another delay, this time enforced by the timelock contract.</p><p>After the time has passed, anyone can execute the proposal. I have the original contract deployer do so.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5a87047e85d2d33aa17cb0025471619b31daa18e3c94386a72a38f2095036cc8.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 USD is successfully minted, governance in action!</p><h2 id="h-concluding-thoughts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Concluding thoughts</h2><p>I hope you found this tutorial helpful!</p><p>To recap, we:</p><ul><li><p>re-created a simplified version of the federal government via on-chain governance, with a governance token (CONGRESS), a governor contract based on Compound’s popular contract, a timelock contract, and a managed ERC20 (USD)</p></li><li><p>walked through creating, voting on, and executing an on-chain proposal in this setup.</p></li></ul><p>Here are links for your reference:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/alexkroeger/the-federal-govt-as-solidity">the repository</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.openzeppelin.com/contracts/4.x/">OpenZeppelin documentation</a></p></li><li><p>Ropsten deployments of the contracts:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ropsten.etherscan.io/address/0x2eeff881aa0c77c289502daa024f152186966a6e">CongressToken</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ropsten.etherscan.io/address/0xe14a123e562b59fd8d7d910f772222ba575bb302">FederalGovernmentTimelock</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ropsten.etherscan.io/address/0x89bbec3be60b9673aef71861093f463f3db6ab1e">FederalGovernment</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ropsten.etherscan.io/address/0x859fe758307e9af3c2ed2190c0a0ff2ef4618156">USDollar</a></p></li></ul></li></ul>]]></content:encoded>
            <author>alex-kroeger@newsletter.paragraph.com (Alex Kroeger)</author>
        </item>
        <item>
            <title><![CDATA[How to use Dune Analytics like a degen]]></title>
            <link>https://paragraph.com/@alex-kroeger/how-to-use-dune-analytics-like-a-degen</link>
            <guid>NhCGGT9l4jrqYtkV60NW</guid>
            <pubDate>Tue, 16 Nov 2021 21:35:39 GMT</pubDate>
            <description><![CDATA[Querying events from unverified contractsSo you want to write a Dune query for some quick and dirty analysis, but the contract isn’t verified on Dune! *starts sobbing uncontrollably 😭😭* But degens aren’t deterred! With a little understanding of Ethereum events and a little effort, you can be on your way to querying. In this post we’ll walk through analyzing some data from a contract that is yet to be verified on Dune--Juicebox’s Terminal V1 contract that is being used by Constitution DAO. I...]]></description>
            <content:encoded><![CDATA[<h1 id="h-querying-events-from-unverified-contracts" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Querying events from unverified contracts</h1><p>So you want to write a Dune query for some quick and dirty analysis, but the contract isn’t verified on Dune! *starts sobbing uncontrollably 😭😭*</p><p>But degens aren’t deterred! With a little understanding of Ethereum events and a little effort, you can be on your way to querying.</p><p>In this post we’ll walk through analyzing some data from a contract that is yet to be verified on Dune--Juicebox’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0xd569d3cce55b71a8a3f3c418c329a66e5f714431#code">Terminal V1 contract</a> that is being used by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.constitutiondao.com/">Constitution DAO</a>.</p><p>I realized partway through writing this tutorial that Richard Chen already used the methodology I’m discussing to create a query for summing the amount given by each contributor to ConstitutionDAO, so to give due credit to the Gandalf of Dune wizards, I’ll be breaking down the steps to get to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/244441/456924">his result</a>.</p><h3 id="h-ethereum-events" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Ethereum events</h3><p>Events (also known as logs) on Ethereum are a way of storing historical information that is significantly cheaper than contract storage. While this data can’t be accessed by contracts, they can be easily queried from an application.</p><p>They are typically used as records of pertinent information from a transaction, so they are also great for analysis.</p><p>In this example, we’ll look at <code>Pay</code> events from the Terminal V1 contract, which have information on who paid into the DAO and how much. I pasted an example of one of these events below <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/tx/0xd0f984134f92d81e243a83af1305afc9e827bec1606e681aaa61b695bb6e98b4#eventlog">from Etherscan</a>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4932bb9d80ab4777a272e5a57f4e6a8a6cd54a9a4c7fe30cebe0132a033d70c2.png" alt="An example Pay event from tx 0xd0f...8b4" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">An example Pay event from tx 0xd0f...8b4</figcaption></figure><h3 id="h-getting-the-events-we-want" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Getting the events we want</h3><p>Dune Analytics has a table of all the events that take place on Ethereum--<code>ethereum.logs</code>. But how do we get the events we want?</p><p>Events have up to 4 indexed parameters to make querying from a node easier and faster. Dune stores these in <code>ethereum.logs</code> as <code>topic1</code>, <code>topic2</code>...</p><p>The first topic is almost always the “event signature,” an identifier for the event.</p><p>There are two ways to get this:</p><ol><li><p>Grab it from an example event on a block explorer</p></li><li><p>Compute it yourself using the event information</p></li></ol><p>For the first method, if you have an example transaction and the contract is verified on Etherscan, you can grab the first topic from the event log. In our on-chain example, you can see that the signature is `0x3deb3bb81c337489381f7685daa204d30e6a265dac443a718949c258e3e17317`.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/25ff6a317838e667915096c3384c54b5461967eb8c94bff4fea7559dffbeec57.png" alt="Event signature as the first topic." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Event signature as the first topic.</figcaption></figure><p>Say you don’t have an example transaction handy or the contract isn’t verified on Etherscan, doesn’t matter if you’re a degen! If you know the event name and parameter types, you can compute the signature yourself!</p><p>The signature is the keccak256 hash of the event name and argument types:</p><p><code>keccak256(&apos;eventName(arg1 type,arg2 type…)&apos;)</code></p><p>For the <code>Pay</code> event, it’s:</p><p><code>keccak256(&apos;Pay(uint256,uint256,address,uint256,string,address)&apos;)</code></p><p>Using node and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.npmjs.com/package/ethers">`ethers`</a>, we can run:</p><pre data-type="codeBlock" text="const ethers = require(&apos;ethers&apos;);

ethers.utils.keccak256(ethers.utils.toUtf8Bytes(&apos;Pay(uint256,uint256,address,uint256,string,address)&apos;));
"><code>const ethers <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'ethers'</span>);

ethers.utils.keccak256(ethers.utils.toUtf8Bytes(<span class="hljs-string">'Pay(uint256,uint256,address,uint256,string,address)'</span>));
</code></pre><p>We get the same result:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a3638563c11cb43ca47f0dde598937d0d782a073cc9064175bacb09a5528119a.png" alt="Using ethers to compute to the event signature." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Using ethers to compute to the event signature.</figcaption></figure><p>Finally, we can use the event signature and contract address to fetch these events <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/247743">in Dune</a>:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/47cd9e88a94b406bc63b974beaeafeb687f6e6e996c8793340360c9ab779efdd.png" alt="Using the event signature and contract address to grab the events we want." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Using the event signature and contract address to grab the events we want.</figcaption></figure><h3 id="h-using-the-event-data" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Using the event data</h3><p>Now that we have the event data, we can start to look at some numbers.</p><p>Looking back at our sample event, let’s look at what information we have:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/23bc971ce5cda7944865eb3d8f406f1841ce9d63188cd307893a5c4d63b8b55b.png" alt="Event parameters." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Event parameters.</figcaption></figure><p>We want to see the contributions to ConstitutionDAO by contributor. You can see there is a <code>projectId</code> field on which we’ll want to filter, a <code>beneficiary</code> field showing who contributed (and therefore should be the beneficiary of DAO tokens), and an <code>amount</code> that we’ll want to sum.</p><p><code>ethereum.logs</code> has 4 columns (topic1-topic4) for each of the (up to) 4 indexed fields. <code>projectId</code> will be in <code>topic3</code> and <code>beneficiary</code> will be in <code>topic4</code>. <code>amount</code> is concatenated with the other non-indexed parameters in the <code>data</code> field.</p><p>You’ll notice that the data fields (<code>topic*</code> and <code>data</code>) are not nice decoded values. Rather, everything is a bytes data type.</p><p>For addresses, we want to the hex string anyway, so all we want to do is effectively cut out the leading zeros in the bytes with the <code>substring</code> function like so:</p><p><code>SUBSTRING(topic4 FROM 13 FOR 20) AS address_from_topic4</code></p><p>For <code>projectId</code>, we want to get a numeric value. We can use the <code>bytea2numeric</code> function to convert the raw bytes to a decimal number like so:</p><p><code>BYTEA2NUMERIC(topic3) AS project_id_from_topic3</code></p><p>Last but not least, we need to combine the previous two functions to get the <code>amount</code> parameter. Since <code>amount</code> is one of the non-indexed parameters, it is concatenated with the other non-indexed parameters (<code>note</code> and <code>called</code>). Since <code>amount</code> is the first parameter and it’s 32 bytes long, we can clean it up like so:</p><p><code>BYTEA2NUMERIC(SUBSTRING(data FROM 1 FOR 32)) AS amount_wei_from_data</code></p><p>You’ll notice that this is a large number, because it is the amount of ether specified in its smallest denomination--wei. We need to divide it by 10^18 to get the amount in ether:</p><p><code>BYTEA2NUMERIC(SUBSTRING(data FROM 1 FOR 32)) / 1e18 AS amount_ether_from_data</code></p><p>We can check all these parameters are correct by comparing <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/247747">our query</a> with our sample event.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f8396bc0ebadf52fbd8b7151cdf6c3e7131b264025348471098753f544ca1681.png" alt="Spring data cleaning." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Spring data cleaning.</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/dfed7ab62b057b8f4458ae9ba755f8f5409970a0301ce032a58e6c099d3802ff.png" alt="The sample event." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">The sample event.</figcaption></figure><p>Looks great!</p><p>If we apply everything discussed herein, we end up with <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/queries/244441/456924">Richard Chen’s query</a> for the largest contributors:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/034f7fe40ed3ae5469a98514b83bf50286202316d6ea9a5b22f49005487b74ee.png" alt="The final query." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">The final query.</figcaption></figure><p>Go forth and query, my fellow degen wizards.</p><h2 id="h-appendix" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Appendix</h2><p>One thing to watch out for when doing this is are parameters that aren’t a fixed width in bytes. For example, in the <code>Pay</code> event, there is a <code>note</code> field of type <code>string</code>. The <code>string</code> type can be an arbitrary length, so if you’re querying in the data field for a parameter after it (like <code>caller</code>), it takes some extra tricks. I’ll leave that to you to figure out :)</p>]]></content:encoded>
            <author>alex-kroeger@newsletter.paragraph.com (Alex Kroeger)</author>
        </item>
        <item>
            <title><![CDATA[Liquidity miners: hands of 💎 or 🧻?]]></title>
            <link>https://paragraph.com/@alex-kroeger/liquidity-miners-hands-of-or</link>
            <guid>cPZshwHuUR5Xt69Zj0xB</guid>
            <pubDate>Mon, 15 Nov 2021 00:41:51 GMT</pubDate>
            <description><![CDATA[Liquidity mining is the practice of distributing governance tokens to users that provide capital to a protocol. Announcing it in May 2020, the first protocol to put this into practice was Compound. Regarding the aim of liquidity mining, the post states: “The distribution of COMP will become a core mechanic of the Compound protocol. All users and all applications built on top of Compound will continuously, and automatically receive governance rights, for free—in order to shape the future of th...]]></description>
            <content:encoded><![CDATA[<p>Liquidity mining is the practice of distributing governance tokens to users that provide capital to a protocol. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/compound-finance/expanding-compound-governance-ce13fcd4fe36">Announcing</a> it in May 2020, the first protocol to put this into practice was Compound. Regarding the aim of liquidity mining, the post states:</p><p><em>“The distribution of COMP will become a core mechanic of the Compound protocol. All users and all applications built on top of Compound will continuously, and automatically receive governance rights, for free—in order to shape the future of the protocol.”</em></p><p>In other words, the initial goal of liquidity mining was to distribute governance tokens to users who would then become active participants in protocol governance.</p><p>Since that time, liquidity mining has been used by a number of DeFi protocols to distribute governance tokens from their treasuries, including <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://uniswap.org/blog/uni/">Uniswap</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.aave.com/developers/guides/liquidity-mining">Aave</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://curve.fi/">Curve</a>, and others.</p><p>It’s worth discussing these programs, because many aren’t cheap. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://uncommoncore.co/a-new-mental-model-for-defi-treasuries/">Hasu and Monetsupply</a> argue that native tokens in DAO treasures are the “crypto-equivalent of authorized but unissued shares.” Paying out these liquidity incentives puts new tokens into circulation that otherwise might have stayed in the treasury, imposing a cost to existing token holders in the form of dilution.</p><p>In this excellent <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://messari.io/article/state-of-compound-q3-2021?utm_source=ryanwatkins_&amp;utm_medium=tweet&amp;utm_campaign=state-of-compound-q3">financial statement</a> put together by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/RyanWatkins_">Ryan Watkins</a>, we see that in Q3 2021, Compound protocol paid out $76M worth of tokens in liquidity incentives. Compare that number to the amount of grant money paid out over that same period--a measly $100K.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2c32eaca917a29facc1d5ad75b0b3f8799daf17700839619f2d35a47e3c64bc6.png" alt="A macro overview of Compound, h/t Ryan Watkins at Messari." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">A macro overview of Compound, h/t Ryan Watkins at Messari.</figcaption></figure><p>In this post I’ll try to answer the following questions:</p><ul><li><p>Is liquidity mining achieving one of its initial goals on Compound--have those that received large amounts of COMP become active governance participants?</p></li><li><p>What changes should be made to Compound’s liquidity mining?</p></li></ul><h2 id="h-has-liquidity-mining-on-compound-distributed-governance-rights-to-active-governance-participants" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Has Liquidity Mining on Compound Distributed Governance Rights to Active Governance Participants?</h2><p>Thanks to the transparency of public blockchains, this is a question we can answer with the help of data. There are two simple questions we can ask regarding whether or not those who receive liquidity mining rewards become active participants:</p><ol><li><p>Do they retain an economic interest in Compound (or do they simply dump the COMP they accrue)?</p></li><li><p>Do they participate in governance (do they vote on on-chain proposals)?</p></li></ol><p>To answer this, I analyze the top 100 accounts by accrued COMP from liquidity mining. To make the analysis easily reproducible, I choose a specific block height--13570000 (2021-11-07).</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a63afaa571dd03db5596229332d37fd6db5039f5009567b3d9924e65dfd4cc2a.png" alt="Summary statistics for the top 100 COMP-accruing addresses." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Summary statistics for the top 100 COMP-accruing addresses.</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f72e33869c68a5327d9030131c60f3eb8086bbab77778a2a19edc285c58c1074.png" alt="Top 10 COMP-accruing addresses." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Top 10 COMP-accruing addresses.</figcaption></figure><p>These top 100 accounts have accrued 809K COMP (roughly $271M at current prices), representing 69% of all COMP mined.</p><p>Yet very few of these accounts are COMP hodlers. Only 19% have kept greater than 1% of the COMP they claimed; only 7% have kept greater than 50%. Do recipients of liquidity mining rewards retain an economic interest in Compound protocol? No.</p><p>It stands to reason that if very few of these addresses are hodlers, very few vote. Indeed, only <em>1 address</em> from the top 100 <em>ever voted</em> on a Governor Bravo proposal.</p><p>Do the users who mine the most COMP work to shape the future of the protocol? The answer is a clear “no.”</p><h2 id="h-what-changes-should-be-made-to-compounds-liquidity-mining" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What changes should be made to Compound’s liquidity mining?</h2><p>I would argue that these results demonstrate that liquidity mining on Compound is broken. Large quantities of COMP are being given out to folks with little interest in governing the protocol.</p><p>Below I list and explain some ideas for changing Compound’s distribution strategy.</p><p><strong>Scale back liquidity mining</strong></p><p>Right now, many large COMP accruers are engaging in recursive borrowing and lending--they deposit tokens, borrow tokens using that deposited collateral, deposit the borrowed tokens, borrow more, and so on. This practice isn’t economically useful to the protocol.</p><p>This practice is encouraged by the fact that both borrowing and lending on Compound reap liquidity mining rewards. This practice could be scaled back if only one side of the market was incentivized.</p><p>I suggest only incentivizing lending. Lenders, I believe, are more likely to be interested in passively earning yield and have an interest in good governance (likely exercised via delegation for smaller participants) of the Compound protocol in the long run so that their lent funds are safe. Only incentivizing lending could help reduce the practice of recursive borrow/lending while still attracting this target user profile.</p><p><strong>Create a vesting schedule for accrued tokens</strong></p><p>To better align incentives of liquidity miners with the protocol, there could be a vesting schedule specifying when the underlying COMP tokens become redeemable. This COMP with a vesting schedule could itself be tokenized, and these tokens could retain governance rights.</p><p>A counterpoint to this approach is that it’s possible to hedge away price risk from COMP by shorting it. However, hedging incurs a cost to those who do it, and so there will be a greater incentive to mine from those who wish to take on price exposure from COMP than from those who wish to immediately hedge away price exposure once mined.</p><p><strong>Governance mining</strong></p><p>An alternative to liquidity mining is an idea put forth by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/jacobpphillips">Jacob Phillips</a> called “<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/0x6507C1693c70Ebab813BCeBD8Bcd9152Cfffa91b/WDKGKpfLy-9nX_reyecjdGDA8CRsZ9sy3jk-JjliFnc">governance mining.</a>” Instead of distributing governance tokens to those who lock up capital in the protocol, you could distribute tokens based on contributions in proportion to their impact on the protocol.</p><p>The underlying assumption here is that contributors--those who put time and effort into the protocol--will be much more aligned with its long-term success of the protocol than yield farmers.</p><p>One issue here is the subjectivity of determining what contributions are the “highest impact”--the simplest solution would be to use an agreed-upon community multisig to estimate impact and distribute tokens accordingly.</p><p>A simpler form of this idea would be to simply dramatically expand the grants program to reward contributors based on bounties.</p><p><strong>Give users an explicit voice in governance</strong></p><p>I agree that in DeFi, users of protocols should have a say in how those protocols are run. However, giving governance tokens to users doesn’t necessarily provide a “user voice” in governance if most of the tokens are being dumped on the market.</p><p>An alternative to granting governance tokens to users is to just give users an explicit voice in the protocol. A certain amount of voting power (say ⅓), could be reserved for protocol users in proportion to their economic stake (total value borrowed or lent, for instance).</p><h2 id="h-closing-thoughts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Closing Thoughts</h2><p>Liquidity mining programs merit more attention in DeFi governance more broadly--are they achieving their intended objectives? In the case of Compound, it seems clear that liquidity mining incentives are a poor way to turn users into stewards of the protocol.</p><p>A separate goal of liquidity mining could be to simply to attract capital and drive usage, though this use case also merits a careful cost-benefit analysis and I think that should probably be viewed as a short-term way to create network effects rather than a long-term growth strategy.</p><p>Regardless of what you think the goals of liquidity mining should be, the scales of these programs merits more careful measurement and consideration of their costs and benefits.</p><h2 id="h-appendix" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Appendix</h2><p>For more detail on the data analysis used in the post, check out this <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.google.com/spreadsheets/d/1WuazK4KYGUv2OV3IDBuyEIIVCjVcaWl1TkmoInHqWLo/edit?usp=sharing">Google sheet</a> or this <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/alexkroeger/comp-liquidity-mining-data-analysis">Github repo</a>.</p><h2 id="h-addendum" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Addendum</h2><p>Added 11/15:</p><p>h/t to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/adamscochran">Adam Cochran</a> for suggesting to look at delegations in addition to votes. More of the top 100 addresses (16%) delegated voting power at some point than voted (only 1%).</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2ec0e4b162026012f4684d95e6ce3f1023e89b80b50295330a2afc7ef8846333.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>]]></content:encoded>
            <author>alex-kroeger@newsletter.paragraph.com (Alex Kroeger)</author>
        </item>
    </channel>
</rss>