<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Ivan Bogatyy on Medium]]></title>
        <description><![CDATA[Stories by Ivan Bogatyy on Medium]]></description>
        <link>https://medium.com/@ivanbogatyy?source=rss-1ff4cbafc96f------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*tFDsRc5Nep5tQycig7lHLw.png</url>
            <title>Stories by Ivan Bogatyy on Medium</title>
            <link>https://medium.com/@ivanbogatyy?source=rss-1ff4cbafc96f------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 03:27:40 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@ivanbogatyy/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[How to build an Ethereum mining pool]]></title>
            <link>https://medium.com/dragonfly-research/how-to-build-an-ethereum-mining-pool-6be356520b7a?source=rss-1ff4cbafc96f------2</link>
            <guid isPermaLink="false">https://medium.com/p/6be356520b7a</guid>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[mining]]></category>
            <dc:creator><![CDATA[Ivan Bogatyy]]></dc:creator>
            <pubDate>Thu, 29 Jul 2021 16:39:00 GMT</pubDate>
            <atom:updated>2021-07-29T16:39:00.420Z</atom:updated>
            <content:encoded><![CDATA[<p>Mining pools are major power players in the Ethereum ecosystem. With miner-extractable value (“MEV”) growing exponentially, the passing of EIP-1559 and the upcoming merge, they have become louder and increasingly important actors in the ecosystem.</p><p>For the uninitiated: mining pools are software providers who enable many mining machines to pool together their mining power and share rewards. Mining pools are essential in PoW mining on two levels: first, because earnings for individual miners are highly volatile, and second, because setting up the software infrastructure around mining is increasingly complex. By pooling resources, individual miners can lower variance and have a more predictable business.</p><p>But with this power comes great responsibility, and mining pools hold a lot of power. This is because mining pools ultimately decide which blocks get worked on by their miners and which transactions are included in those blocks. Mining pools decide on what MEV gets extracted and who gets to extract it, they vote on the gas limit, and they take part in major political battles. That’s why it’s essential to Ethereum culture that the barrier to entry for mining pools be as low as possible, to maximize decentralization.</p><p>When MiningDAO set out to build our own independent pool, we were surprised to find that it was incredibly challenging! There’s very little open and publicly shared info on how to run a competitive mining pool, and a lot of the open-source software is out of date. So we figured: let’s fix that by releasing an open-source, step-by-step guide.</p><p>Building a pool consists of two parts: (1) setting up a full node client with good peer-to-peer networking and fast processing speed, and (2) connecting the full node to pool software that manages hashrate and distributes workload across all the miners. Here, we’ll cover both.</p><p><strong>This guide comes from our first-hand experience building the </strong><a href="https://miningdao.io/"><strong>MiningDAO.io</strong></a><strong> pool, and outlines how we brought our uncle rates from 10%-14% down to approximately 4%-5%, on par or better than some top-10 pools.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/994/1*qFiDLsY_reghxSYM1g1k4Q.png" /></figure><h3>1) Set up Ethereum full node client</h3><p>Running a mining pool requires running an Ethereum full node client. This client will be responsible for receiving new blocks and pending transactions, as well as producing its own blocks and broadcasting them to other nodes. This section covers how to properly set up one’s full node client.</p><h3>1.1) Server hardware requirements</h3><p>Running a fully synced node requires fairly good hardware. We recommend at least 32GB RAM, and at least 2TB SSD storage (syncing the chain with HDD will take forever).</p><p>Bandwidth is important as well. It is preferable to co-locate as close as possible to other nodes, to receive new blocks as soon as possible. We recommend cloud-hosted dedicated machines on services popular with other pools: <a href="https://www.ovhcloud.com/en/bare-metal/">OVH</a> and <a href="https://www.hetzner.com/dedicated-rootserver">Hetzner</a> in Europe, Alibaba and AWS in Asia.</p><h3>1.2) Geth or OpenEthereum? Geth!</h3><p>The next decision to make is which Ethereum client to use. The most popular and well-tested choices are Geth and OpenEthereum (née Parity). Geth leads on protocol development and is always up-to-date.</p><p>For comparison, we did some small-scale experimentation with Parity-2.7.2 (latest stable branch before the OpenEthereum refactoring) and OpenEthereum, but both had poor results with block import times and block production times, leading to unacceptably high uncle rates. We welcome anyone to perform a more thorough A/B test and <a href="/service/mailto:contact@miningdao.io">reach out to us</a> with more data, but at the current stage we simply recommend Geth.</p><p>Here are the flags we use:</p><pre>geth --datadir=/ssd/gethdata --syncmode=fast --cache=21000<br> --maxpeers=250 --txpool.globalslots=1000<br> --http --http.api=eth<br> --miner.etherbase=&#39;0xADDRESS&#39; --mine --miner.threads=0<br> --miner.extradata=&#39;MiningDAO&#39;<br> --miner.notify=&#39;http://127.0.0.1:8107&#39; &amp;&gt;&gt; ~/geth-log.txt</pre><p>Here --cache=21000 means to allocate 21GB for in-RAM state storage (the most Geth can handle), and the remaining flags will be explained below.</p><p>More importantly, the modifications to the Geth code we will describe below can be found <a href="https://github.com/bogatyy/go-ethereum/">here</a> as a repo to download, or <a href="https://gist.github.com/bogatyy/de048d747c73ca4069c142899c0071fb">here</a> as a patch to apply.</p><h3>1.3) Minimize frequency of empty blocks</h3><p>Two things destroy value for miners: mining uncle blocks, and mining empty blocks. In fact, the two are almost equally bad: uncle block rewards are 1.75 ETH, and empty block rewards are 2 ETH, with no transaction fee surplus in both cases. For comparison, full blocks with transaction fees typically bring 3-4 ETH in total rewards, and sometimes a lot more. So why do mining pools sometimes <a href="https://etherscan.io/block/12737189">produce</a> empty blocks, and how can one minimize their frequency?</p><p>When another pool mines a fresh block (say at height N), any other blocks at height N are likely to become uncles. So whenever a new block is found, Geth instantly switches the miners&#39; jobs to mine an empty block at height N+1. This empty block does not have transaction fees, but that is still better than mining blocks destined to become uncles. Subsequently, geth constructs a &quot;real&quot; block at height N+1, and switches the miners&#39; jobs once again. Constructing such a &quot;real&quot; block takes time (0.1-0.3 seconds), hence the two-step process. But in that interim 0.1-0.3 seconds-long period miners are working on an empty block.</p><p>It might be tempting to collect all the pending transactions to maximize fees, but getting greedy with --txpool.globalslots substantially increases the amount of processing Geth has to do to construct a &quot;real&quot; block (up to 1 second and more). We recommend values no larger than 1000 or 2000.</p><p>For more details on this, check out <a href="https://github.com/ethereum/go-ethereum/issues/21899">https://github.com/ethereum/go-ethereum/issues/21899</a></p><h3>1.4) Minimize frequency of uncle blocks</h3><p>With empty blocks out of the way, we can get started on the hard part. To minimize uncle rates, two things are key:</p><ol><li>when other pools produce new blocks, learn about it as quickly as possible</li><li>when your pool produces a new block, propagate it as widely as possible (so others start mining on top of it)</li></ol><p>The first step to good p2p is, as explained earlier, running your full node on a cloud server with good bandwidth next to other nodes.</p><p>Second, good bandwidth allows the node to handle more direct peers, thus reducing the number of p2p hops necessary to receive new information. The Geth flag for the number of peers is --maxpeers.</p><p>Below we will explain a few more nuanced and powerful tricks to maximize block import speed and block propagation speed.</p><h4>1.4.1) Use bloXroute</h4><p><a href="https://bloxroute.com/">bloXroute</a> is a service dedicated to improving connectivity between miners and lowering their uncle rates. Most pools are connected to bloXroute, and even major established pools <a href="https://medium.com/bloxroute/the-secret-weapon-f2pool-used-to-tackle-its-uncle-rate-1ecb6fe47ef8">report</a> significant improvements from using bloXroute. <a href="https://medium.com/keeperdao/a-performance-benchmark-on-mempool-services-9e68bf070952">Measurements</a> performed by KeeperDAO further confirm the massive advantage bloXroute holds over comparable services.</p><p>Our experiments showed significant improvements as well. On a freshly-synced node with default peer settings, approximately 90% of all new blocks come from bloXroute first (and only 10% from all other peers). Even after our node has been fine-tuned to connect to top peers, still 40%-60% of new blocks come from bloXroute first.</p><p>After following the bloXroute setup tutorial, don’t forget to <a href="https://docs.bloxroute.com/gateway/gateway-installation/adding-the-gateway-as-a-trusted-peer">add the bloXroute node into the “trusted peers”</a> set for your Geth, we will need that later. <a href="https://github.com/ethereum/go-ethereum/blob/4fcc93d9229e99b14d3d1500f05ada6ba1f789bb/p2p/server.go#L113">Trusted</a> peers are pre-set nodes that Geth will always connect to, irrespective of the random peer initialization process. Trusted peers also do not count against the connections limit. Adding the bloXroute gateway to trusted peers ensures Geth will not accidentally drop that connection.</p><p><strong>We further recommend connecting to Taichi Network.</strong> Taichi is a block propagation network developed by Sparkpool. Connecting to it can be done by adding the Taichi <a href="https://taichi.network/">endpoints</a> to the same trusted peers file.</p><h4>1.4.2) Propagate your blocks aggressively</h4><p>Whenever Geth successfully mines a new block, it sends the block to propagate across the network. By default, Geth only propagates it to a random subset of size sqrt(n_peers), who then propagate the block to some of their peers, and so on. This mechanism is not ideal even if all peers were equally useful, but it is especially detrimental when some peers are more powerful than others and these peers end up not being included in the subset.</p><p>In particular, the first thing to do upon mining a new block is to send it to bloXroute, so that it will be forwarded to all the other participating mining pools. If the bloXroute gateway doesn’t end up in that random sqrt(n_peers) subset, your chances of getting uncled go way up!</p><p>Next, you’d want to send the block to the highest-quality peers, and then to all the remaining peers.</p><p>We have open-sourced the <a href="https://github.com/bogatyy/go-ethereum/commit/13dad64b82a2b488a10d345da511514219c52732">following Geth patch</a> and recommend applying it to your client. It propagates all newly mined blocks to all trusted nodes (including bloXroute), and then to all remaining peers.</p><h4>1.4.3) Cultivate the most well-connected peers</h4><p>Vanilla Geth is designed for maximum decentralization and a flat network structure. This choice works well for hobbyists and supports a robust ecosystem of <a href="https://www.ethernodes.org/">thousands</a> of nodes. However, as we’ve already seen in the previous section, these defaults do not work as well for nodes that perform critical responsibilities and have significant dollar costs associated with failures.</p><p>In reality, not all peers are equally useful. Some have slow connections and will neither supply new blocks nor help your blocks propagate. Others, especially the nodes of other mining pools, will produce a constant stream of new block data. Following advice from Sparkpool, we <a href="https://github.com/bogatyy/go-ethereum/commit/3506b916afb01cf9ed0622c62f38daa094ae2800">tweaked our Geth</a> to log which peers were the first to send us a new block. Collecting that data for several months allowed us to figure out the best peers to always keep connected to (via the “static”/”trusted” node settings in Geth). <a href="https://gist.github.com/bogatyy/d4cafa354e0c2e04809ce527f616a476">Here</a> is a Python script we used to process that data and convert it into a trusted_nodes.json list that Geth can ingest.</p><p>Because MiningDAO is present in each geozone (North America, Europe, Asia), we have data-mined the lists of top peers for each geozone. Unfortunately, we cannot share the node IPs publicly to avoid the risk that these nodes will be DDoSed. Can probably share privately on serious inquiries with good justification. Also happy to share our own nodes in each geo for other pools to connect!</p><h3>2) Set up mining pool software</h3><p>Once the full node is set up properly, the next step is to set up the mining pool software itself. This software will be responsible for handling connections from all the individual miner rigs, keeping track of worker shares, and managing payouts.</p><h3>2.1) Pick pool software</h3><p>We briefly analyzed the following 4 options: <a href="https://github.com/coinfoundry/miningcore">miningcore</a>, <a href="https://github.com/sammy007/open-ethereum-pool">open-ethereum-pool</a>, <a href="https://github.com/zone117x/node-open-mining-portal">NOMP (node open mining portal)</a>, and <a href="https://github.com/MPOS/php-mpos">MPOS (mining portal open source)</a>. We later learned about <a href="https://github.com/flexpool/solo">Flexpool Solo</a> but did not experiment with it.</p><p>We had a great experience with Miningcore for two reasons. First, it keeps all past data on disk in an SQL database, unlike open-ethereum-pool, which keeps data only in RAM via Redis. Disk storage offers stability against reboots and ability to analyze historical data. Second, we enjoyed the highly readable, object-oriented code of Miningcore.</p><p>Ultimately, MiningDAO ended up implementing our own pool software, written in Go for speed and modeled after Miningcore. We expect to open-source our implementation soon, but in the meantime we recommend using Miningcore.</p><h3>2.2) Fix pool software latency</h3><p>A major hiccup we encountered while using Miningcore is the way it processes work updates. By default, Miningcore pings the full node RPC every 0.5 seconds to see if the latest job has changed. This setup may work for other cryptocurrencies with longer block times (it would be a negligible problem for Bitcoin with 10-minute blocks), but for Ethereum such a setup leads to unacceptably high uncle rates.</p><p>For context, there is an easy way to calculate the increase in uncle rates from any processing delay. Block times are <a href="https://en.wikipedia.org/wiki/Poisson_distribution">Poisson-distributed</a>, which means that no matter how long it has been since the last mined block, the probability of finding the next block in the next second (or millisecond or whatever) is always the same. For example, Ethereum targets 13-second block times, which means the probability of a block being mined in the next second is always 1 sec / 13 sec ~= 7.7%. So if your mining pool has a 0.1 sec delay anywhere in the pipeline for any reason, it will have 0.1 sec / 13 sec ~= 0.77% extra uncle blocks as a result of that delay. The uncle blocks will come from that 0.1 sec period of time that your miners are working on an outdated job.</p><p>Back to Miningcore. Using the formula above, a 0.5 second delay in updating the miners’ job will lead to 0.5 sec / 13 sec ~= 4% extra uncle blocks (absolute, not relative percentage). Naturally, such a high rate of unforced errors is unacceptable. We have experimented extensively with lowering the update frequency from 0.5 seconds down to 50 milliseconds and below, but found that setting rather unreliable: the updates were still significantly delayed.</p><p>A better solution is to make use of Geth’s notifyWork feature, so that Geth proactively sends job updates to the mining pool software as soon as they appear. We patched Miningcore to support this option, and <a href="https://github.com/Mining-DAO/miningcore">released</a> the modification. After transitioning to notifyWork, we found the communication delays between Geth and Miningcore to become practically negligible, and thus our uncle rates significantly improved.</p><h3>Conclusion</h3><p>Hopefully this post proves useful and leads to more people running Ethereum mining pools or solo-mining, helping keep Ethereum open and decentralized. To summarize, we started with vanilla Geth on default settings and vanilla Miningcore implementation. This default setup produced uncles at a rate of approximately 10%-14%. Progressively applying the modifications outlined here brought our uncle rate <a href="https://etherscan.io/address/0xbbbbbbbb49459e69878219f906e73aa325ff2f0c#uncle">down to 4%-5%</a>, comparable or better than some existing top-10 pools (the Etherscan uncle rate is a bit higher because we sometimes experiment in prod).</p><p>Our Geth modifications can be found <a href="https://github.com/bogatyy/go-ethereum">here</a> as a repo and <a href="https://gist.github.com/bogatyy/de048d747c73ca4069c142899c0071fb">here</a> as a patch. Our Miningcore modifications can be found <a href="https://github.com/Mining-DAO/miningcore">here</a>, and a corresponding pool config file can be found <a href="https://gist.github.com/bogatyy/420e789b3c05e3983ceb9a3966cb305c">here</a>.</p><p>If you have further ideas on how to improve this setup, please send us a <a href="https://github.com/Mining-DAO/docs">pull request</a> or an <a href="/service/mailto:contact@miningdao.io">email</a>!</p><p><em>Miningcore speedup developed by </em><a href="https://twitter.com/themelnikov"><em>Alexander Melnikov</em></a><em>. Many thanks for the suggestions and ideas that came from </em><a href="https://medium.com/@alexandreobadia"><em>Alex Obadia</em></a><em> (</em><a href="https://medium.com/flashbots"><em>Flashbots</em></a><em>), </em><a href="https://twitter.com/eyalmarkov"><em>Eyal Markovich</em></a><em> and </em><a href="https://twitter.com/sunlearnstorock"><em>Shen Chen</em></a><em> (</em><a href="https://medium.com/bloxroute/"><em>bloXroute</em></a><em>), </em><a href="https://twitter.com/xuxin5108"><em>Xin Xu</em></a><em> and Dr. Yang Ze (</em><a href="https://medium.com/@Eth_SparkPool"><em>Sparkpool</em></a><em>), Chris (</em><a href="https://medium.com/flexpool"><em>Flexpool</em></a><em>) and </em><a href="https://twitter.com/hosseeb"><em>Haseeb Qureshi</em></a><em> (</em><a href="https://twitter.com/dragonfly_cap"><em>Dragonfly Capital</em></a><em>).</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6be356520b7a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/dragonfly-research/how-to-build-an-ethereum-mining-pool-6be356520b7a">How to build an Ethereum mining pool</a> was originally published in <a href="https://medium.com/dragonfly-research">Dragonfly Research</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing MiningDAO]]></title>
            <link>https://medium.com/mining-dao/introducing-miningdao-1e469626f7ad?source=rss-1ff4cbafc96f------2</link>
            <guid isPermaLink="false">https://medium.com/p/1e469626f7ad</guid>
            <category><![CDATA[defi]]></category>
            <category><![CDATA[mining]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[decentralization]]></category>
            <dc:creator><![CDATA[Ivan Bogatyy]]></dc:creator>
            <pubDate>Mon, 17 May 2021 16:54:07 GMT</pubDate>
            <atom:updated>2021-05-25T16:16:45.243Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>MiningDAO is a protocol aiming to make block production on Ethereum transparent, trustless, and decentralized. The most urgent use-case is miner-extractable value (“MEV”).</strong></p><p><strong>The protocol allows anyone to propose entire blocks to be mined, with a reward attached for mining them. Mining pools can select the blocks with highest rewards, all without ever knowing the actual contents of the proposed blocks. We expect MiningDAO to be the most profitable choice for mining pools due to enhanced opportunities for earning MEV. Compared to existing systems, MiningDAO minimizes reliance on centralized servers and assumptions of honest miner behavior.</strong></p><p><strong>To showcase MiningDAO, we have built a mining pool that follows the protocol at </strong><a href="https://miningdao.io/"><strong>https://miningdao.io/</strong></a></p><h3>Why MiningDAO?</h3><p>Algorithmic arbitrage on decentralized finance protocols, better known as “miner-extractable value” (<a href="https://arxiv.org/abs/1904.05234">MEV</a>) is a large and growing industry. It started small, at approximately $1M/year in 2017 (on <a href="https://twitter.com/el33th4xor/status/917906450978082816">Bancor</a> and <a href="https://hackingdistributed.com/2017/08/13/cost-of-decent/">EtherDelta</a>), and grew to be ~$500M/year by current estimates.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*iMcu7EWGtuiLX8LE" /><figcaption><a href="https://explore.flashbots.net/"><em>https://explore.flashbots.net/</em></a></figcaption></figure><p>There are multiple actors in the space that play different roles in MEV. First, there are independent arbitrageurs and algo-trading funds, who aim to maximize their profits within the fixed rules of the game. Second, there are mining pools: they are responsible for forming all Ethereum blocks, and thus make the ultimate decisions on how transactions are included. Until recently, mining pools simply followed the default rules implemented in geth and Parity. Third, there are companies trying to change the way the game is played: BloXroute offers private transactions that avoid public-by-default mempools, Flashbots offers more profitable transaction sets for mining pools, KeeperDAO offers a decentralized “hiding game”. Our approach is largely inspired by <a href="http://smartpool.io/docs/smartpool.pdf">SmartPool</a>.</p><p>By default, we’d expect most of the MEV to go to miners via arbitrageurs competitively <a href="https://en.wikipedia.org/wiki/Dollar_auction">bidding away</a> all the profit. Nevertheless, several mining pools kickstarted attempts to speed up this transition, and capture even greater MEV profits. Ethermine (tied for largest Ethereum pool with Sparkpool) <a href="https://twitter.com/jgarzik/status/1379117480296202243">runs its own</a> in-house frontrunning bots. ArcherDAO partnered with several smaller pools (2miners, Ezil, etc) to build and run in-house bots for them, splitting the profits 50/50. These MEV battles, while fascinating to watch, lead to wasted resources and potential consensus instability: consider <a href="https://github.com/Defi-Cartel/salmonella">Salmonella</a>, a clever attack that stole ~120 ETH from Ethermine’s in-house front-running bot, or Ethermine’s <a href="https://twitter.com/bertcmiller/status/1381296074086830091">revenge</a>, that selectively used transactions from an orphaned block to exploit a Flashbots user. These problems demand a generalized and robust solution.</p><p>MiningDAO is building a decentralized and transparent protocol for block formation, where the same rules apply to everyone. We propose an open-source, modular infrastructure, with no secretive lock-in components, where all miners and all block producers participate on equal footing. Anyone with an Ethereum address can propose the next block to be mined (via a block <em>sealhash</em>), and attach a bounty for successfully mining it. The mining pools would then mine on the highest-bounty proposal, brute-forcing nonces while remaining oblivious to the actual contents of the block. Other than putting everyone on equal footing in relation to MEV, this design greatly increases Ethereum’s censorship resistance.</p><h3>How MiningDAO works</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/826/1*V4zq6_4q40BLrkIywzrECw.png" /><figcaption>high-level overview of MiningDAO protocol</figcaption></figure><p>To simplify, the protocol works like a DEX orderbook for blocks, so if you’re familiar with 0x, it should be easy to visualize what’s going on.</p><ol><li>Block producers deposit ETH into a “DEX” smart contract, locked with some time delay.</li><li>To propose a block, a block producer signs an off-chain commitment, containing two variables: (a) block <em>sealhash</em>, and (b) proposed <em>block reward</em>.</li><li>At any given moment, miners look for the highest-reward block proposal at the current block height, and bruteforce to find a <em>nonce</em> that would seal that block.</li><li>Whenever such a <em>nonce</em> is found, it is immediately forwarded to the block producer, as well as posted to the smart contract, with the corresponding <em>block reward</em> taken out of the block producer’s deposit.</li></ol><p>Initially, our protocol relies on a centralized coordinator to ensure all nonces are correct and timely (to avoid mining long-stale shares).</p><h3>Why go beyond Flashbots</h3><p>Our functionality has substantial similarities to Flashbots, as well as substantial differences, so it’s worth explaining the benefits of our approach.</p><p>First, we want to <strong>minimize centralization risk</strong> in Ethereum block formation. The status quo used to be that top 5 pools produced ~65% of all Ethereum blocks. That’s <a href="https://www.sciencedirect.com/science/article/pii/S0306457321000844">already risky</a>, but at least no single pool ever got close to 50% hashrate that would let it dominate the network. As it stands, Flashbots routes ~80% of the hashrate, substantially increasing the risk that it can dictate the future Ethereum trajectory (e.g. by routing transactions via a <a href="https://github.com/flashbots/pm/discussions/45">proprietary proxy</a>). We believe alternative coordination mechanisms, focusing on minimalism and decentralization, would benefit the robustness and censorship-resistance of Ethereum.</p><p>Second, we believe <strong>our technology is a substantially better design</strong>. MiningDAO is the first protocol to offer truly private transactions that do not rely on an honesty assumptions by miners. The protocol can work end-to-end without revealing any of the transactions to miners, up until the point a block is mined. Further, <strong>our block auction is open-bid</strong>, which is substantially more convenient for arbitrageurs: they know in advance whether they’re winning and can always bid up, instead of having to build complicated pricing models based on past history.</p><p>Ultimately, we see a parallel here with the evolution of cryptocurrency trading, as it progressed from centralized exchanges running on AWS, to decentralized exchanges running on smart contracts. Our mission is to facilitate a similar evolution for block production on Ethereum.</p><h3>Roadmap towards full decentralization</h3><p>The V1 that we launched today is completely permissionless and private for block producers, but not trustless (it requires a centralized coordinator to ensure block producers cannot be exploited by miners). For pools that would like to join, the system is currently whitelist-based to protect against double-claiming work. Below is our plan to further decentralization.</p><p>The trustless V2 design will incorporate the following primitives:</p><ol><li>SmartPool-style share validation to verify submitted nonces (We intend to log all shares on L2 with merkle root logged in L1)</li><li>Gas savings: validating PoW on every block is prohibitively costly (<a href="https://ropsten.etherscan.io/tx/0xcdad249a063a8f1e78e126bf0bf1d26fc0d6bac76b79ce5051e7d868cac1d35c">~3M gas</a>), but an optimistic challenge-response validation can obviate this cost (i.e. only run the ~3M gas verification in case of disputes)</li><li>ChainLink “first seen” oracle for pending transactions to punish timing-based griefing attacks</li></ol><h3>How to participate</h3><p>We are building an open, permissionless system, where anyone can participate on equal footing.</p><p>As such, we are providing the following endpoints for participants:</p><ul><li><strong>For miners:</strong> we have launched our own MiningDAO <a href="https://miningdao.io/">pool</a>, which automatically mines the best available block template. The pool takes zero fees. MiningDAO runs multiple failover block producers (both vanilla and MEV-extracting), so that mining in the MiningDAO pool is guaranteed to yield more ETH than any non-MEV-extracting pool. <a href="https://miningdao.io/help">Here</a> are the instructions for how to point your rigs to MiningDAO pool.</li><li><strong>For mining pools:</strong> we welcome all mining pools to supplement their income via MiningDAO block templates. If you have any questions about how to integrate MiningDAO with your hashrate, please send us an email at <a href="/service/mailto:contact@miningdao.io">contact@miningdao.io</a>.</li><li><strong>For arbitrageurs: </strong>we have <a href="https://github.com/Mining-DAO/mev-geth#quick-start">two endpoints</a> available. For easy onboarding, we welcome Flashbots-style transaction bundles. For more sophisticated or composite strategies, we welcome block producers to bid on block templates directly.</li></ul><h3>Learn more</h3><ul><li>Follow us on <a href="https://twitter.com/Mining_DAO">Twitter</a> for key updates</li><li>Join on <a href="https://discord.gg/Tusb3cFVTc">Discord</a> and <a href="https://t.me/miningdao">Telegram</a> for discussions</li><li>Explore &amp; contribute on <a href="https://github.com/Mining-DAO">Github</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1e469626f7ad" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mining-dao/introducing-miningdao-1e469626f7ad">Introducing MiningDAO</a> was originally published in <a href="https://medium.com/mining-dao">Mining DAO</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Breaking Mimblewimble’s Privacy Model]]></title>
            <link>https://medium.com/dragonfly-research/breaking-mimblewimble-privacy-model-84bcd67bfe52?source=rss-1ff4cbafc96f------2</link>
            <guid isPermaLink="false">https://medium.com/p/84bcd67bfe52</guid>
            <category><![CDATA[mimblewimble]]></category>
            <category><![CDATA[grin]]></category>
            <category><![CDATA[bitcoin]]></category>
            <category><![CDATA[privacy]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <dc:creator><![CDATA[Ivan Bogatyy]]></dc:creator>
            <pubDate>Mon, 18 Nov 2019 14:50:00 GMT</pubDate>
            <atom:updated>2019-11-22T03:09:33.577Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>TL;DR: Mimblewimble’s privacy is fundamentally flawed. Using only $60/week of AWS spend, I was able to uncover the exact addresses of senders and recipients for 96% Grin transactions in real time.</strong></p><p><strong>The problem is inherent to Mimblewimble, and I don’t believe there’s a way to fix it. This means Mimblewimble should no longer be considered a viable alternative to Zcash or Monero when it comes to privacy.</strong></p><p>In the last two years, Mimblewimble has grown in popularity as an up-and-coming, lightweight privacy protocol. Mimblewimble was invented in 2016 by a pseudonymous hacker known as Tom Elvis Jedusor, who dropped a <a href="https://github.com/mimblewimble/docs/wiki/MimbleWimble-Origin">text description of the protocol</a> into an IRC chat and then disappeared. Since then, Mimblewimble was most famously implemented in the “fair launched” privacy coin <a href="https://grin.mw/">Grin</a>, the VC-backed projects <a href="https://tlu.tarilabs.com/protocols/mimblewimble-1/MainReport.html">Tari</a> and <a href="https://beam.mw/">BEAM</a>, and is even being considered for <a href="https://github.com/litecoin-project/lips/blob/master/lip-0003.mediawiki">integration into Litecoin</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FwYhRyFg9KpwFf7kj-nBrw.png" /></figure><p>Several researchers have hypothesized a possible privacy weakness in Mimblewimble <a href="https://www.tokendaily.co/blog/mimblewimble-the-good-and-the-bad/">[1]</a><a href="https://www.reddit.com/r/Mimblewimble/comments/91cvyl/mimblewimble_transactions_linkable_by_any/">[2]</a><a href="https://medium.com/scalar-capital/behind-mimblewimble-cd9da78a00e9">[3]</a><a href="https://medium.com/human-rights-foundation-hrf/privacy-and-cryptocurrency-part-iii-should-you-use-a-privacy-coin-22dc71732a2f">[4]</a>. My contribution is to demonstrate the precise way to perform an attack, prove its viability on a live network, and measure its efficacy. In live testing on Grin, I was able to unmask the flow of transactions with a 96% success rate. Therefore, it’s now clear that <strong>Mimblewimble should not be relied upon for robust privacy.</strong></p><p><a href="https://github.com/bogatyy/grin-linkability">Here</a> is a more technical deep-dive into this attack, complete with open-source code to reproduce it, data collected, and a technical FAQ. What follows in this article will be a high-level, intuitive explanation of linkability, how the attack works, and what it means for privacy tech.</p><h3>What is linkability?</h3><p>It’s important to understand what this attack means and what it doesn’t mean.</p><p>This attack does <em>not</em> let us determine the <strong><em>amounts</em></strong> that people are getting paid. Mimblewimble successfully obfuscates payment amounts using vanilla elliptic curve cryptography (<a href="https://github.com/mimblewimble/grin/blob/master/doc/switch_commitment.md">Pedersen commitments</a>). What this attack <em>does</em> let us do is determine <em>who paid who</em>. In other words, it lets us link transactions together and determine the flow of payments.</p><p>It might not be obvious why that’s a big deal.</p><p>Say Coinbase knows that a certain address belongs to a Venezuelan individual named Daniel. You, an American user, try to cash out on Coinbase. But after deobfuscating the transaction graph, Coinbase determines that you received money from Daniel, though they don’t know how much you received. Due to <a href="https://www.treasury.gov/resource-center/sanctions/programs/pages/venezuela.aspx">OFAC restrictions</a> on Venezuela, Coinbase shuts down your account. (Naturally, exchanges will know a lot about the transaction graph because they have KYC information on users who cash out into fiat.)</p><p>Or say an authoritarian government knows that a certain address belongs to a political dissident. You send that dissident a small donation. Later, when you send your Mimblewimble transfer to the local exchange, that exchange shares your transaction data with the government. Since the government can see the entire transaction graph, they now know that you supported a political dissident.</p><p>These attacks would not be possible in Zcash. This is because Zcash is unlinkable — or in other words, every Zcash shielded transaction has a large <strong>anonymity set</strong>. The anonymity set is essentially the set of transactions that your transaction is indistinguishable from. Think of it like blending into the crowd: the larger the anonymity set, the larger “crowd” your transaction is mixed into.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xVX9TM9D9mLkwVuD" /></figure><p>In Zcash, each shielded transaction’s anonymity set includes all shielded coins. This is the maximum possible anonymity from an information theoretic perspective.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CjUEdAXVowpuv96c" /></figure><p>In Monero, each transaction’s anonymity set is the set of all (believable) decoy transactions. While the Monero client lets you specify the size of the decoy set, the current default is 11. (Monero has its own issues around <a href="https://www.finder.com.au/can-monero-ever-achieve-private-transactions">securely sampling decoys</a>, but I believe it mostly works, <a href="https://www.youtube.com/watch?v=9s3EbSKDA3o">give or take</a>.)</p><p>It was originally believed that Mimblewimble’s anonymity set includes all the transactions in the same block and looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*LSDf1fL4WlWljZks" /></figure><p>But in reality, it looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*v8MyAJ6AFqlN3bB2" /></figure><p>This whittles down Mimblewimble’s anonymity set to a single address.</p><p>To be clear, this is not an indictment of Grin. I have great respect for the Grin community and core developers, who have all been tremendously helpful in answering my questions.</p><p>Grin still affords a stronger privacy model than Bitcoin or other non-privacy coins, since amounts are safely encrypted. But Mimblewimble provides a strictly weaker privacy model than Zcash or Monero. This makes it insufficient for many real-world privacy use cases.</p><h3>A high-level overview of the attack</h3><p>So how exactly can you trace the transaction graph in Mimblewimble?</p><p>I noted that despite encrypting the payment amounts, Mimblewimble still leaves a linkable transaction graph. But the protocol designers were aware of this, so Mimblewimble uses two chief techniques to combat linkability: the first is <strong>full-block cut-through aggregation</strong>, and the second is <strong>Dandelion</strong>.</p><p>The idea behind block cut-through is that as transactions are accumulated within a block, those transactions get aggregated into one “super-transaction”. That “super-transaction” basically looks like one giant <a href="https://bitcoinmagazine.com/articles/coinjoin-combining-bitcoin-transactions-to-obfuscate-trails-and-increase-privacy-1465235087/">CoinJoin</a> — essentially, all of the inputs and outputs are tossed into one giant bucket, with no easy way to determine who paid who within that bucket. There’s just a bunch of inputs going to a bunch of outputs, with amounts obscured.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Fn4Z8eOSmCLPb_vn" /><figcaption>Two transactions are aggregated together into a block. After the aggregation, it’s impossible to tell whether it was Alice or Carol who paid Bob.</figcaption></figure><p>Sounds solid, right? Only one problem: this CoinJoin has to be built up one transaction at a time. Because transactions are continually being created and broadcasted from separate places, if you run a sniffer node that picks up all transactions before cut-through aggregation is finished, it’s trivial to unwind the CoinJoin. Any sniffer node can just observe the network and take note of the original transactions before they get aggregated. It’s pretty straightforward if you just archive all messages you observe in the P2P network.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*LEFBxw_cm1BQZOeq" /></figure><p>Wait — really? Is that all there is to it?</p><p>Well, there’s another line of defense that the Grin team put up:<strong> Dandelion protocol</strong>. Dandelion is a networking technique <a href="https://bitcoinmagazine.com/articles/anatomy-anonymity-how-dandelion-could-make-bitcoin-more-private/">developed by researchers at CMU</a> that attempts to obfuscate the originator of a transaction.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*eFe2jXaYVQiGBugw" /><figcaption><em>A transaction propagating with Dandelion. Stem phase (maximizing anonymity) followed by fluff phase (maximizing spread)</em></figcaption></figure><p>Normally, in a cryptocurrency like Bitcoin, the originator of a transaction just shouts their transaction to all of their peers, and it quickly cascades through the P2P network. But in Dandelion protocol, every transaction broadcast starts with a secret game of telephone. The originator will whisper their transaction to just one peer, who whispers it to one other peer, and so on in a chain. After a random number of hops, the final peer will shout out the transaction just as in Bitcoin. But this peer is so far removed from the originator, for any observer it’s impossible to tell who the chain started with.</p><p>This works great for obfuscating the IP of the transactor. But Dandelion has a second function within Grin: it just so happens to defeat sniffer archive nodes. Because every transaction starts off in a Dandelion chain, whenever two transactions cross in their Dandelion chains, they’ll get aggregated early. If this happens, then by the time the transaction is broadcast for everyone to observe, a sniffer node cannot disaggregate them. They’ve already been CoinJoined.</p><p>Against a sniffer node, this is Grin’s principal defense against linkability. But even this defense can be defeated.</p><p>By default, each Grin node connects to 8 other peers. But by jacking up the number of peers, I can connect my sniffer node to every other node in the network. Assuming I stay alive long enough, eventually almost every node will connect to me, making me a <strong>supernode</strong>.</p><p>Once I am a supernode, there’s a high probability that I will be on the Dandelion path for any transaction. Therefore, the only way that I cannot catch a transaction before it is aggregated is if two transactions both <em>intersect in their Dandelion path before I see either of them</em>. If I see either transaction before they’re aggregated, I can use simple set subtraction to disaggregate them.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*QhEzLle-e42jLjRt" /><figcaption><em>A supernode is connected to every other node and will instantly get any transaction that enters fluff phase, before it can be merged with other transactions for anonymity.</em></figcaption></figure><p>In my attack, I was able to link 96% of all transactions while only connecting to 200 peers out of the total 3000 peers in Grin’s network. But if I wanted to spend a bit more money, I could easily connect to 3000 nodes to disaggregate almost all transactions. I also don’t have to do this as a single supernode; the same attack works by launching 3000 separate nodes with unique IPs, each only connected to one peer. As long as I’m sniffing all the transaction data and dumping it into a central master database, the attack works just the same.</p><h3>So is Mimblewimble salvageable?</h3><p>It depends. I believe that Grin, as currently envisaged, has no clear path to unlinkability. Simply ratcheting up the Dandelion factor can be easily combated by a motivated attacker, as I discuss in the <a href="https://github.com/bogatyy/grin-linkability#faq">technical writeup</a>.</p><p>But linkability aside, Mimblewimble still has unique and valuable properties! It allows cut-through aggregation, which is an effective compaction technique for full nodes, and efficiently hides transaction amounts. If you want strong privacy, you can always combine Mimblewimble with another protocol that obscures the transaction graph, such as in <a href="https://ethresear.ch/t/ethereum-9-send-erc20-privately-using-mimblewimble-and-zk-snarks/6217">Ethereum 9¾</a> (which combines Mimblewimble with a Zerocash-style commitment-nullifier scheme).</p><p>But it’s clear that Mimblewimble on its own is not strong enough to confer robust privacy.</p><p>Bitcoin is now 11 years old, but cryptocurrencies are still in their infancy. It wasn’t that long ago that devastating bugs were uncovered in both <a href="https://fortune.com/2019/02/05/zcash-vulnerability-cryptocurrency/">Zcash</a> and <a href="http://hackingdistributed.com/2017/04/19/monero-linkability/">Monero</a>. This is to be expected — most of the interesting technologies are still in the realm of basic science.</p><p>But this is how science always advances: we propose new theories, and then repeatedly knock them down, until what’s left standing has stood the test of time.</p><p><em>Thanks to </em><a href="https://medium.com/@hosseeb"><em>Haseeb Qureshi</em></a><em> for major help in putting together this write-up and for the anonymity set illustrations. Additional thanks to </em><a href="https://medium.com/@olegostroumov"><em>Oleg Ostroumov</em></a>, <a href="https://medium.com/@leanthebean"><em>Elena Nadolinksi</em></a><em>, </em><a href="https://medium.com/@fouda"><em>Mohamed Fouda</em></a><em>, Lucas Ryan and </em><a href="https://medium.com/@nadertheory"><em>Nader Al-Naji</em></a><em> for reviewing drafts of this post. And a huge thanks to </em><a href="https://medium.com/@jstutzman"><em>Jake Stutzman</em></a><em> (</em><a href="https://medium.com/nearprotocol"><em>NEAR Protocol</em></a><em>) for the Dandelion and block aggregation illustrations.</em></p><p><em>For more of my writing, follow me on Twitter at </em><a href="https://twitter.com/IvanBogatyy"><em>https://twitter.com/IvanBogatyy</em></a><em>.</em></p><p><strong><em>Disclosure</em></strong><em>: Dragonfly Capital abides by a no-trade policy for the assets listed in this report for 3 days from the date of publication.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=84bcd67bfe52" width="1" height="1" alt=""><hr><p><a href="https://medium.com/dragonfly-research/breaking-mimblewimble-privacy-model-84bcd67bfe52">Breaking Mimblewimble’s Privacy Model</a> was originally published in <a href="https://medium.com/dragonfly-research">Dragonfly Research</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How we made $100K trading CryptoKitties]]></title>
            <link>https://medium.com/@ivanbogatyy/how-we-made-100k-trading-cryptokitties-2d69aebe715b?source=rss-1ff4cbafc96f------2</link>
            <guid isPermaLink="false">https://medium.com/p/2d69aebe715b</guid>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[investing]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[gaming]]></category>
            <dc:creator><![CDATA[Ivan Bogatyy]]></dc:creator>
            <pubDate>Tue, 10 Apr 2018 13:55:36 GMT</pubDate>
            <atom:updated>2018-04-23T19:55:42.218Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*nApf9UzfooT9L9B-." /><figcaption><em>Founder Cat #4, the main protagonist of the story.</em></figcaption></figure><p><strong>By now everyone has heard of CryptoKitties, a cute game that went viral to the point of overloading the whole Ethereum network. This is the inside story behind how we made $107K investing in CryptoKitties and briefly set the record for the largest sale ever (currently second-largest). Later, we made ~$8K running an automated arbitrage bot. While playing the speculation game at the height of the mania was exciting, the bot was fairly technically involved and will be interesting to people who want to learn blockchain engineering in general.</strong></p><p>As I was toying with my Ethereum smart contracts on a regular Saturday night (December 2), something was clearly off: transactions were stuck and took much longer than usual to confirm. A <a href="https://etherscan.io/txsPending">quick investigation</a> showed there were 10–20 times more pending transactions than usual, and many of them were going to the same mysterious address, <a href="https://etherscan.io/address/0x06012c8cf97bead5deae237070f9587f8e7a266d">0x06012..66d</a>. This is how I first learned of the now-famous CryptoKitties game.</p><h3>Investment thesis</h3><p>Next morning I called <a href="https://medium.com/@olegostroumov">Oleg Ostroumov</a>, a close buddy who runs a top crypto hedge fund in Russia to discuss this unusual phenomenon. While the CryptoKitties game was merely a curiosity for me, Oleg immediately spotted a lucrative investment opportunity. First, we were clearly among the earlier entrants. Second, the game looked like it had all the precursors of going viral, similar to Pokemon Go, and was in the early stage of a hockey stick explosion.</p><p>Now the question was, which Kitties should we buy? The marketplace offered 4 ways to sort Kitties: cheapest first, most expensive first, newest first, oldest first (<em>note: the website had been redesigned since</em>). The first 3 options are clearly transient: you can always put a cheaper, more expensive, or a newer Kitty on the market. Oldest, however, is like diamonds: forever. Thus we decided to buy single-digit Founder Cats, despite their already hefty price tags: somebody just snatched them at 25 ETH and re-listed the lineup at 50 ETH ($25K), with Founder Cat #1 trading even higher at 150 ETH.</p><p>Oleg bought Founder Cats <a href="https://www.cryptokitties.co/kitty/4">#4</a>, <a href="https://www.cryptokitties.co/kitty/6">#6</a>, <a href="https://www.cryptokitties.co/kitty/8">#8</a> at 50 ETH each ($25K at the time), and I put up $5K for a 20% equity stake in Founder Cat #4. We were pretty optimistic about the mania and re-listed the Kitties at 250 ETH, 5x the purchase price.</p><p>As a side-note, we wasted about an hour because of posting a low gasPrice, and had to reinstall MetaMask (at the time it did not have the “resend transaction with increased gasPrice” feature — it was added right after). Lesson learned: if you’re making a $25K purchase, do not try to save $20 on fees.</p><p>Right after hanging up on the call I considered the chances that this was going to be my personal record yet for the most ridiculous way to waste $5K. Probably pretty high.</p><h3>The subtle art of exiting the top</h3><p>Over the next days (December 2–5), the game entered the viral explosion phase. Given the addictiveness, it was pretty hard to focus on anything else. Clearly, the craze was not going to last: the game mechanics were way simpler than say Pokemon Go, with just two functions available, either buy or breed them to produce new ones. We assumed it could last for a couple weeks tops, so it was important to formulate a rational exit strategy in advance and stick to it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*MMnWUMqi_HbbG3Sf." /><figcaption><em>Google Trends for “cryptokitties”. The breakdown by country is very interesting as well.</em></figcaption></figure><p>We used three metrics. First, Google Trends for “CryptoKitties” showed how frequently people Googled information about the game, which is a pretty good leading indicator of interest. Second, <a href="https://ethgasstation.info/gasguzzlers.php">GasGuzzlers</a> shows the top gas-consuming smart contracts on the network and the share of gas they consume (for CryptoKitties it was ~4% when we entered and ~20% at peak popularity). Third, we watched the market conditions and the prices of recent sales on a very nicely built app, <a href="https://kittysales.herokuapp.com/">https://kittysales.herokuapp.com/</a>.</p><p>On December 4–5, several less prestigious Kitties (#35, #78, #87) sold for almost 200 ETH, so we were confident our listing price was well-adjusted. However, December 5–6 was the top on every metric, and by the end of December 6 the popularity was clearly trending downhill. Observing this, we had an emergency call on December 6 trying to figure out what to do with the Kitties, none of which sold at our listed 250 ETH price yet. I wanted to re-list the Kitty at a lower price of 100 ETH, whereas Oleg was steadfast on sticking to 250 ETH. Given our disagreement about the value of the Kitty, we did the obvious arbitrage: I sold my 20% stake to him at a 100 ETH “Kitty valuation”, essentially doubling my money on the spot. Little did I know I’d only be happy about this deal for about 20 minutes…</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Hc-AG9x5fNZqPJck." /><figcaption><a href="https://kittysales.herokuapp.com/"><em>kittysales.herokuapp.com</em></a><em> leaderboard, with Founder Cats #18 and #4 being top sales.</em></figcaption></figure><p>I kept watching the marketplace out of curiosity. Now, 20 minutes after Oleg bought me out, I saw our Founder Cat #4 sold at the original 250 ETH price. I was so confident it was Oleg generating game activity for his merchandise, I barely bothered to ask him. When I did, however, I learned the full power of HODLing: it was a genuine purchase, we had no idea who was the buyer, and he’d just set the world record for selling a collectible on the blockchain.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0ExgLvNknWiROlRt." /><figcaption><em>GasGuzzlers showing most popular Ethereum contracts. The current 0.92% volume is but a shadow of the former 25% glory.</em></figcaption></figure><h3>Automatic arbitrage</h3><p>Having had such a lucky start to the game, we discussed what else we could do with it. Peak hype was clearly over and ridiculous prices for the rarest Kitties were unattainable, but the long tail remained: people still wanted to play, and to get some kind of Kitty for themselves.</p><p>So we decided to try running an automatic arbitrage bot on the long tail of cheaper Kitties. Like any reseller strategy, it essentially consisted of the following three steps:</p><ul><li>Determine <a href="https://en.wikipedia.org/wiki/Equivalence_class">clusters</a> of Kitties that <strong>should</strong> be priced roughly the same. The parameters we looked at were Rarity, Cooldown and Generation (only Gen 0 and Gen 1 were expensive enough to bother). Kitties with same values across these 3 parameters were deemed equivalent (ignoring cuter artwork or Cattribute variations).</li><li>Buy underpriced items within each class. In our case, we only bought the cheapest Kitty across every parameter set.</li><li>Resell the acquired item for more. In our case, we wanted to avoid a race to the bottom with other potential resellers, so we listed each Kitty at slightly below the second-cheapest price (similar to Google’s <a href="https://en.wikipedia.org/wiki/Generalized_second-price_auction">second-price auction</a>).</li></ul><p>After exploring several blockchain libraries, we found refactoring my previous <a href="https://hackernoon.com/front-running-bancor-in-150-lines-of-python-with-ethereum-api-d5e2bfd0d798">Bancor front-running code</a> to work best. The strategy was: watch for transactions that put Kitties on sale, buy out immediately if it matches the criteria. This instant reaction mechanism is pretty similar to front-running except it’s more like post-running: one cannot put the “buy” transaction before the “list on the auction” transaction, so it needs to happen immediately after. On a more technical level, there are several ways to implement this:</p><ul><li>Whenever you see a pending “listing” transaction, try to buy out the Kitty <strong>within the same block</strong>. You could either send the “buy” transaction with a slightly lower price (e.g. if the “list” transaction pays 25 gwei for gas, you can pay 24.999 gwei), or, alternatively, pay precisely the same. In the former case, you risk being just below the block cutoff threshold, and then your transaction would stay “pending” for hours if the activity spikes. In the latter case, you risk miners putting your “buy” transaction in front of the “list” transaction (since gasPrice is the same, the order can be arbitrary and depends on miner software), which would result in our transaction failing.</li><li>Wait until the “listing” transaction is confirmed, and send out the “buy” transaction right after with a <strong>very high gasPrice, ensuring confirmation within the next block</strong>.</li></ul><p>You wouldn’t expect this cute game to be a particularly dense arena, but we had competitors who employed each of those options trying to snatch the Kitties! And since each of those options had its own benefits, we had to implement all of the strategies to have the highest chance (this can be done either the naive way, by running the 3 versions from 3 accounts, or by re-using the nonce within the same account, but further technical details are beyond this story).</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/543864c731ab881cde4b47e1a11ecf54/href">https://medium.com/media/543864c731ab881cde4b47e1a11ecf54/href</a></iframe><p>Another possibility we considered was the following: assume you want to buy a Kitty, and its price is slowly going down as determined by the linear time auction. Instead of buying it right away, one can wait until another contender appears and front-run their purchase, achieving lowest possible price. As much fun as it would have been to be such evil masterminds, the market was crashing too fast to warrant spending that much attention on any single big-ticket Kitty.</p><h3>Aftermath</h3><p>More than a month after the peak hype subsided, we received a pleasant surprise: somebody bought out Kitty #6 as well. 29 ETH was below the initial purchase price, but decent money nevertheless (plus Ethereum doubled in price at the time).</p><p>The remaining Kitty #8 gets Oleg’s undivided care and adoration. The Kitty has its own laptop stickers, t-shirts and even a custom-made silver pin. I hear it is about to get its own Instagram channel too.</p><p>In the end, it was a very hands-on lesson on speculative manias. I undershot and Oleg overshot, but both of us almost precisely doubled our money, which was a pretty amazing outcome. Yes, there is absolutely no guaranteed intrinsic value or price floor for imaginary Kitties. Nevertheless, one can still play this game and even win. And of course, it was practically impossible to predict where the top of the bubble would be, although we came pretty close.</p><p>As for my ~$5000 profit from this adventure, I decided to donate it to <a href="https://www.mccme.ru/index-e1.html">MCCME</a>’s <a href="https://lksh.ru/">Summer Informatics School</a>, an exceptional coding bootcamp in Russia where I studied as a high-schooler, as well as the <a href="https://freedom.press/donate/">Freedom of the Press Foundation</a>. Here I doubled my money again thanks to Google’s generous Gift Match Program.</p><p><em>Thanks to </em><a href="https://medium.com/@olegostroumov"><em>Oleg Ostroumov</em></a><em>, </em><a href="https://medium.com/@alinaaseeva"><em>Alina Aseeva</em></a><em>, </em><a href="https://www.linkedin.com/in/aashna-mehra-79717663/"><em>Aashna Mehra</em></a><em>, </em><a href="https://haseebq.com/"><em>Haseeb Qureshi</em></a><em> and </em><a href="https://medium.com/@DavidSmooke"><em>David Smooke</em></a><em> for reading drafts of the story. For more, follow me on Twitter at </em><a href="https://twitter.com/IvanBogatyy"><em>https://twitter.com/IvanBogatyy</em></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2d69aebe715b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Implementing Ethereum trading front-runs on the Bancor exchange in Python]]></title>
            <link>https://medium.com/@ivanbogatyy/front-running-bancor-in-150-lines-of-python-with-ethereum-api-d5e2bfd0d798?source=rss-1ff4cbafc96f------2</link>
            <guid isPermaLink="false">https://medium.com/p/d5e2bfd0d798</guid>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[ico]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[bitcoin]]></category>
            <dc:creator><![CDATA[Ivan Bogatyy]]></dc:creator>
            <pubDate>Tue, 10 Oct 2017 14:36:10 GMT</pubDate>
            <atom:updated>2020-01-11T22:12:05.380Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ejger5KDxRDQsq8vyW5GKQ.png" /><figcaption>Launching the attack: the green letters look just like on TV</figcaption></figure><p><strong>This post is a deep-dive into programmatically trading on the Ethereum / Bancor exchange and exploiting a game-theoretic security flaw in </strong><a href="https://www.bancor.network/"><strong>Bancor</strong></a><strong>, a high-profile smart contract on the Ethereum blockchain. The full code can be found at </strong><a href="https://github.com/bogatyy/bancor"><strong>https://github.com/bogatyy/bancor</strong></a><strong>. We collaborated with the Bancor team to make sure the current exploit is protected against, although for a little while there would still be a chance to make some beer money for educational purposes.</strong></p><p>Imagine trying to hack Bank of America — except you can read all of their code in advance, all of their transactions are public, and if you steal the money it’s irreversible. Sounds like a paranoid worst-case scenario? Well, this is exactly the setup Ethereum smart contract developers have to deal with every day. Bitcoin and the blockchain technology unlocked tremendous possibilities in international payments, and the Ethereum further magnified it by allowing to manage these payments through programs called <strong><em>smart contracts</em></strong>. However, smart contracts also give hackers a much easier setup for attacks.</p><p>Front-running is one such attack. The term originated in the stock market, back in the days when trades were executed on paper, carried by hand between the trading desks. A broker would receive an order from a client to buy a certain stock, but then place a buy order for themselves in front. That way the broker benefits from the price increase at the expense of their client. Naturally, the practice is unfair and was outlawed.</p><p>On the blockchain, the problem becomes a lot more severe. First, all the transactions are broadcast publicly. More importantly, blockchain participants across the world are not bound by the same relationship as a broker and their client, so attackers can exploit their knowledge of a pending transaction with impunity.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/503/1*TxVByaqq8P2LoK7VE-3s_A.png" /><figcaption>If you squint hard enough, you can imagine these guys trying to front-run each other</figcaption></figure><p>Several months ago, researchers at Cornell <a href="http://hackingdistributed.com/2017/06/19/bancor-is-flawed/">uncovered</a> that Bancor, an ICO that spectacularly raised over $150M in funding over a few minutes, was vulnerable to front-running. They pointed out that miners would be able to front-run any transactions on Bancor, since miners are free to re-order transactions within a block they’ve mined. While the Bancor team gave a <a href="https://blog.bancor.network/this-analysis-of-bancor-is-flawed-18ab8a000d43">thoughtful response</a>, up until very recently, there has not been any progress on fixing the issue (more on that later).</p><p>Our research goes a step further. In fact, we show that it is both possible and practical to front-run Bancor <strong>as a non-miner</strong>. Which means you don’t need to the lucky miner who happens to mine the block with a Bancor trade to profit from front-running. You simply need to be a regular user monitoring the blockchain to perform this attack.</p><p>Surprisingly, the vulnerability does not seem to have been exploited so far (front-running is readily identifiable on the blockchain), so in this post we’ll examine exactly how one implements such an attack. Turns out, all it takes is about 150 lines of Python to get a working front-running algorithm. We also ran simulations to determine how much money one could make from front-running consistently (spoiler: <strong>an attacker could have had a ~117% ROI on the money they invested into the attack over July and August, chipping away from other Bancor users</strong>). Finally, I executed the attack against a single trade, making<strong>~$150 net of all fees</strong>, after which I returned the money to the person I front-ran and stopped the program.</p><p>Now, I know that relinquishing a working trading strategy would be a cardinal sin to any trader, but as it turns out, I am more curious than greedy. Implementing and countering attacks is not only a fascinating game, but also the cornerstone of advancing cryptographic security. Most importantly, I believe in the long-term impact of the blockchain ecosystem, and for the blockchain economy to fully develop, vulnerabilities like this need to be understood and protected against.</p><p>So let’s dig in.</p><h3>Background</h3><p>Bancor is a protocol for trading and pricing Ethereum <a href="https://ethereum.org/token">ERC-20 tokens</a>, as well as the eponymous token, abbreviated as BNT, with the current market capitalization of approximately 180 million dollars. The core problem Bancor solves is as follows: normally, for a trade to happen, there has to be a buyer and a seller, having opposing desires (to buy and to sell) at the same moment in time. This limitation may be fine for large publicly traded stocks, but for long-tail crypto tokens this can create a serious inconvenience.</p><p>Bancor solves this problem by allowing anyone to trade against a public smart contract, which offers an automatically calculated token price following a precise formula. Essentially, Bancor is fulfilling the role of market-makers in traditional finance. The smart contract has an Ethereum reserve, and as more people buy the token, reserves grow and the price goes up. Consequently, when people sell, the contract adjusts the price to go down, so that the reserve is never depleted entirely. Unlike most other exchanges, where trades are managed off-chain, with Bancor every order is a self-contained Ethereum transaction (money + data).</p><p>Unfortunately, the current setup contains a flaw, allowing anyone to front-run large transactions and make guaranteed profit. Let us expand on what makes the attack possible. When somebody <strong><em>broadcasts</em></strong> a transaction on the Ethereum network, it becomes available to other nodes almost immediately as a <strong><em>pending transaction</em></strong> and is added to the common queue, but it is not <strong><em>confirmed</em></strong> until the <strong><em>block confirmation hash</em></strong> is found by some miner (thus confirming all the transactions in that block), which tends to happen once every ~20 seconds. Further, up until the block is confirmed, the order of the pending transactions is up for grabs, and miners basically <a href="https://github.com/ethereum/go-ethereum/blob/290e851f57f5d27a1d5f0f7ad784c836e017c337/miner/worker.go#L492">sort transactions</a> by how much they’re paid per <strong><em>gas</em></strong> (that is, per unit of computation they’ll have to perform).</p><p>This discrepancy creates an attack vector: any user running a full-node Ethereum client can spot a pending transaction and insert their own transaction in front of it by paying more per gas. If you see a large BUY is about to happen, you know the BNT price will increase (following their deterministic formula), so if you buy in before that transaction you get an instant appreciation of your tokens and a guaranteed return on your investment. Similarly, if somebody sent out a pending SELL, an attacker can sell their tokens in front.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J6_Zn2Pizv9b-G-jKQMekQ.jpeg" /><figcaption>Ethereum blockchain (ordered) and pending transactions (partially ordered, but possible to get in front)</figcaption></figure><p>Given we will be implementing our attack using Ethereum client API, now would be a good time to take a step back and give a general overview of how the Ethereum distributed applications (or DApps for short) landscape looks like. At a high level, implementing DApps is fairly similar to regular Web applications. The backend is a smart contract, running on the Ethereum blockchain, typically implemented in Solidity and then deployed to the network. Then there is client software, which interacts with the backend by sending transactions.</p><p>Just like in the regular world, smart contracts (the backends) receive most of the attention, with many high-profile smart contracts and several high-quality developer guides appearing recently (personally, what I’ve found most useful was fiddling with the examples from <a href="https://solidity.readthedocs.io/en/develop/solidity-by-example.html">Solidity official docs</a>, as well as great intro guides by <a href="http://hudsonjameson.com/training/ic3-2017">Hudson</a> and <a href="https://karl.tech/learning-solidity-part-1-deploy-a-contract/">Karl</a>). However, on the front-end side, I currently do not know of any non-trivial client-side applications (an example of such an application would be a <a href="https://arxiv.org/abs/1701.06726">decentralized poker client</a>, where the majority of compute has to happen off-chain, on the players’ machines). Right now, the only way for users to interact with smart contracts is to send transactions manually, either by running their own full node (for example, by using the geth client), or by relying on third-party web services (like MyEtherWallet). Clearly, this would have to change: the current situation is about as convenient as manually sending POST requests through Telnet every time you wanted to browse the Web.</p><h3>Easy Mode: high-frequency trading by hand</h3><p>The simplest way to confirm the vulnerability is by hand. We will not need any tools except a Web browser and a wallet with some Ether.</p><p>First, separate your Ether between two wallets equally (it will not work from a single wallet). Second, go to MyEtherWallet and, following <a href="https://blog.bancor.network/experimental-simple-bnt-purchasing-aafd51d03b30">Bancor purchase instructions</a>, set up two BUY transactions (do not click Send yet!). You should prepare two equivalent transactions from both wallets, but make sure gas price on the first wallet is lower than on the second.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1CJ7DJC7lhboVizO." /><figcaption>Sending ETH to the Bancor purchase contract automatically returns BNT to your account. Note: mind the gas!</figcaption></figure><p>Now, when it’s set up, click “Send” on the first wallet (with the lower gas price), and then “Send” on the second wallet, with the higher gas price. If you did everything right, the transaction that was submitted second would actually be processed first, and get more BNT per same deposit!</p><p><a href="https://etherscan.io/tx/0xe09de9c9093565e645eb93a74d86c390cb96bec88131abcbefc1b0b889ff5241">Transaction 1</a> <em>(transaction from wallet 1, submitted first, fulfilled second)</em></p><p>BNT tokens received: <strong>11.014424</strong>733254973428</p><p><a href="https://etherscan.io/tx/0x4bf702fef14c4da5beae7f676d93f80316cb872390c480450f43e968dba4c53a">Transaction 2</a> <em>(transaction from wallet 2, fulfilled first, should get better price)</em></p><p>BNT tokens received: <strong>11.014423</strong>186864343663</p><p>Notice the letdown: while the front-running transaction should’ve gotten a better price, it actually got a slightly worse one. Upon careful investigation, I realized this is because the <a href="https://github.com/bancorprotocol/contracts/blob/501564a18c1ddfdfaf5538c98ec383264b5efd6e/solidity/contracts/BancorFormula.sol">rather arcane implementation</a> of the Bancor formula can deviate quite significantly from the <a href="https://drive.google.com/file/u/1/d/0B3HPNP-GDn7aRkVaV3dkVl9NS2M/view">theoretical formula</a>, especially for smaller amounts (specifically, error in 4th digit for 0.1 ETH or roughly $20 transactions). After querying the <a href="https://etherscan.io/address/0x8d10c03bc0889a2edea0de12e455a19ac7395b98">BancorFormula</a> contract for a bit, I learned that even for 1 ETH the precision is not good enough, but if we’re willing to make 10 ETH-sized transactions or larger, we’d actually observe a better price as predicted. The Bancor team recently updated the formula and mentioned it is a lot more accurate. Ultimately, I decided to skip re-doing this experiment with larger transaction sizes or the new formula in favor of the actual front-run.</p><h3>Hard Mode: trading automatically</h3><p>Now, unless we are ready to sit in front of a computer all day and hit refresh on <a href="https://etherscan.io/">etherscan.io</a>, the process needs to be automated. Luckily, most Ethereum clients provide a <a href="https://github.com/ethereum/wiki/wiki/JSON-RPC">JSON RPC</a> to interact with the blockchain and automate away the low-level details of interacting with the blockchain.</p><p>You just need to run a full node client and send API requests to localhost:8545.</p><pre>$ sudo apt-get install software-properties-common<br>$ sudo add-apt-repository -y ppa:ethereum/ethereum<br>$ sudo apt-get update<br>$ sudo apt-get install ethereum<br>$ geth --rpc</pre><p>Here is an example curl request that looks up a transaction by hash (in this case, a huge BUY order on Bancor):</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9a214887788fb1d7fadca892f28ef177/href">https://medium.com/media/9a214887788fb1d7fadca892f28ef177/href</a></iframe><p>Now let’s send the same request using Python:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a0353114726d382dbcda67628c5516e0/href">https://medium.com/media/a0353114726d382dbcda67628c5516e0/href</a></iframe><p>If you got the same output as from curl, congratulations! The hardest part of learning to programmatically interact with the blockchain is already over.</p><p>Now implementing the front-running trader becomes a matter of putting together a few common API requests (pseudocode below for brevity). If the goal is to be maximally efficient, it is better to avoid cashing out in between transactions: front-running can be done in both directions, and it would be the most profitable to only sell once we see a pending sell, and only buy once we see a pending buy:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8578f639202503bddd516c7f243dda9c/href">https://medium.com/media/8578f639202503bddd516c7f243dda9c/href</a></iframe><p>In my case I only wanted to prove that the idea works (and yields non-negligible amounts of money), so I did the front-run once and sold immediately. Better yet, in this case the “loser” of the trade is easy to pin-point (the only person losing money is the owner of the trade being front-ran), so it was easy to return that money too. More details to be found in the <a href="https://github.com/bogatyy/bancor">full code</a> on my GitHub.</p><p>The <a href="https://etherscan.io/tokentxns?a=0xca83bd8c4c7b1c0409b25fbd7e70b1ef57629ff4&amp;p=24">results</a> of the front-run (transactions in reverse chronological order):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sTUpW73PCEFf4ilytzoQlw.png" /></figure><p>We made 0.477 ETH, or a ~0.5% return in less than a minute! I calculated the amounts (my own principal and the threshold for front-running) so that the profit would be at least $100, which I deemed convincing enough for the purposes of my post. Noteworthy, just a few days later there was a whopping <a href="https://etherscan.io/tx/0x551137eb0558015aea760dbd8c8bfc1ee73308b427db547cb92329e3ab1dcc47">5856 ETH trade</a> purchasing Bancor, which would have yielded an approximately 9% return, or about $3000 given the same 100 ETH principal!</p><p>The next part will explain where do these numbers come from and how to calculate the return from front-running a given trade.</p><h3>Simulations &amp; ROI evaluation</h3><p>Let us describe the two core assumptions behind the Bancor pricing system, and the exact formula that is derived from those assumptions. First, Bancor maintains a constant ratio between the <strong><em>traded token</em></strong> market capitalization and total <strong><em>reserve token</em></strong> value. As of right now, the only traded token is BNT, and the only reserve token is ETH. Assume there is approximately 70K ETH in reserves (which is roughly the case) and the reserve ratio is 10%. This means the whole market cap of the system is implied to be 700K ETH, and the price per BNT is determined from this total market cap, divided by total BNT supply. If somebody buys BNT with ETH, the whole ETH amount is added to the reserves, thus pushing the price up (there was more value added to the reserves than tokens issued), increasing the value of everybody else’s tokens. Conversely, selling BNT reduces the reserve and thus the price per token (this way, the reserve never gets depleted, you just get less and less of it per token).</p><p>The second assumption is that a large trade should be equivalent to making a set of smaller trades of the same size (so to determine the final price, one would have to calculate an integral of <strong><em>Price d(Size)</em></strong>). Turns out these two assumptions are sufficient to uniquely define the behavior of the system in all cases. For those with a strong mathematical inclination, there is <a href="https://drive.google.com/file/d/0B3HPNP-GDn7aRkVaV3dkVl9NS2M/view">proof</a> available. Here are the resulting formulas:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gWxTvemJfgdAXS17IxnW7Q.png" /></figure><p>For our practical purposes though, the exact formulas are not really necessary (and as we have learned, the actual implementation is not very precise anyway). Approximating the pricing formula with the linear part of its <a href="https://en.wikipedia.org/wiki/Taylor_series">Taylor’s series</a>, we get:</p><p>NEW_PRICE ~= OLD_PRICE * (1 + DEPOSIT / RESERVE_BALANCE)</p><p>Interestingly, the RESERVE_RATIO is not a part of the approximation. I’ll skip the full derivations here, but basically, it cancels out in the numerator and the denominator, so the only thing that ends up mattering is RESERVE_BALANCE = TOTAL_MONEY * RESERVE_RATIO. This pricing formula is a good approximation as long as the deposit is much smaller than the total reserve. So if BNT has 70K ETH in reserves, and somebody invests 700 ETH, the price goes up by 700 / 70K = 1%. If somebody withdraws 700 ETH out of the system, the price drops 1%. Thus in both cases front-running those transactions would give us instant 1% ROI. <strong>Note that our theoretical approximation matched practice quite well: a </strong><strong>350 ETH trade yielded a </strong><strong>0.477% return, against approximately </strong><strong>0.5% predicted.</strong></p><p>Based on these calculations, I wrote some <a href="https://github.com/bogatyy/bancor/blob/master/simulation.py">code</a> to evaluate how much money could have been made front-running Bancor in July and August. Assuming we leave small transactions alone and only go after big ones (&gt; 100 ETH) so that gas prices don’t really matter, we get:</p><pre>$ python simulation.py<br>...<br>ROI for front-running all transaction &gt;= 100 ETH:<br>July 88.7%<br>August 28.6%<br>With a principal of 100 ETH, that would make you $35190</pre><p><strong>Not bad: an attacker can more than double the money they invested into the attack over a couple months, chipping away from other Bancor users. </strong>In practice, the profitability threshold is smaller than 100 ETH (the total fees one would need to beat come out to a few dollars), though it also depends on the principal invested by the attacker.</p><h3>Front-running other Bancor-<strong>exchangeable tokens</strong></h3><p>While we did show that it was possible, BNT itself is relatively hard to front-run because of the large reserves: its price changes very little between transactions. But for any smaller token the 1 / RESERVE_BALANCE fraction would skyrocket an attacker’s profits and rob honest investors very fast. To prove that, I have deployed my own token following the Bancor Protocol (<a href="https://etherscan.io/address/0xf90a54b20881ece27e3a8e31903e3e75009a0164">address</a>, <a href="https://github.com/bogatyy/bancor/blob/master/solidity/DummyBancorToken.sol">code</a>) and made instant 2X profit front-running a large transaction.</p><p>Our FBT (short for Front-Runnable Bancor Token) was initialized to have a total supply of 1M wei (where wei is the smallest possible unit in Ethereum, equal to 10^-18 ETH ), and the total initial supply of 2M tokens. Given the 10% reserve rate ratio, the implied market capitalization of our token becomes 10M wei , and the price per token 10M / 2M = 5 wei . Now what happens when the front-runner makes a deposit before a large “honest” BUY, but sells after?</p><p><a href="https://etherscan.io/tx/0x11cf84b2a98f5b8d72f5ba63b193aa78ba92d73cf63fa840a3f92d64bf97ee4f">TX1</a>, front-run:1000 wei gives 199 FBT , in line with the price we calculated</p><p><a href="https://etherscan.io/tx/0x2296386f370ebf25d16a1f9f8bf7e35e20d6b9482786342939a399fb796eeb06">TX2</a>: very large buy, increasing the price roughly 2X</p><p><a href="https://etherscan.io/tx/0x0109ae1b29fc24db0d18111f0c6581988a1ac58cfe94dded4f30578a6ea4100e">TX3</a>: attacker withdraws 199 FBT for 1910 wei, doubling their money</p><p><strong>Since the intended use of Bancor is to serve the lesser known tokens (which may not have enough demand and liquidity for regular exchanges), these tokens would naturally have smaller reserves, making this vulnerability especially dangerous. In an extreme case where the reserve is very low and an attacker has a lot of money, they can extract more value from an honest investor’s deposit than the investor would get themselves!</strong></p><p>Further, all of this is possible as a mere full node (that is, a person with a decent laptop). Miners, and especially miner pools, are in a privileged position and can do an order of magnitude more damage. Full-node attackers have to broadcast their transactions and thus risk their principal, whereas miners can mine blocks with their own front-run included, but never reveal it publicly unless they do mine the block. That way, they can profit at no risk or cost to themselves. Further, they can rearrange transactions within a block in whatever way they want, arbitrarily creating winners and losers out of other participants.</p><h3>Ethics</h3><p>Like any new technology, this situation raises very interesting ethical questions. Is the strategy we discussed “hacking”? Is it high-frequency trading? Is it simply an ability to make informed decisions based on public information faster than other investors? Ultimately, is this kind of trading “bad”?</p><p>Personally, I took an easy way out and made the decision that lets me sleep the most soundly: returning the money after proving the point and stopping the program. Nevertheless, I would not have blamed someone in a similar spot if they decided to do otherwise.</p><h3>Solutions</h3><p>Over the past month, <a href="http://haseebq.com/">Haseeb Qureshi</a> and I discussed several solutions with the Bancor team, making sure the vulnerability is contained. Yesterday, the team released a fix that handles most of the risk in practice. Long-term, theoretically robust solutions are fairly complex, and while analyzing those can be a whole different post, I want to briefly mention the options available.</p><p><strong>TL;DR don’t send large transactions and use </strong><a href="https://app.bancor.network/"><strong>Bancor Web3 UI</strong></a><strong> that sets a </strong><strong>minReturn for you.</strong></p><p>One partial solution is to set a minReturn on trades, basically canceling your order if you realize someone squeezed in front of you. This does prevent attackers from making guaranteed money instantly, but raises the question: what is a buyer supposed to do next? The order just revealed their intention to buy, and presumably they still want their Bancor, so they’ll place another buy order sometime in the near future, which will eventually raise the Bancor price and, on average, will profit the attacker just the same.</p><p>Yesterday, the Bancor team released a <a href="https://app.bancor.network/communities/5967699a4a93370018b7b891">Web3 interface</a> that implements the minReturn solution. Longer-term, and assuming perfectly intelligent adversaries, this might lead to some curious Nash equilibria (e.g. front-runners might block trades unless they are allowed a small profit margin, though a lower one than if they were front-running entirely naive users), but right now, this should solve most of the practical risk.</p><p>The Bancor team also suggested setting a universal maxGasPrice, to make sure non-miner front-runners cannot bid higher. This would fully protect the users from non-miner attacks (at a cost of lower liquidity during network congestion), although the original <a href="http://hackingdistributed.com/2017/06/19/bancor-is-flawed/">front-runs by miners</a> would not be affected. This fix will be out soon too.</p><p>More robust solutions would involve a version of the <a href="https://karl.tech/learning-solidity-part-2-voting/">commit-reveal</a> scheme, one of the go-to instruments in a cryptographer’s toolbox. <a href="http://hackingdistributed.com/2017/08/28/submarine-sends/">Submarine sends</a> by Cornell researchers proposes the most beautiful and general solution that I know of. However, given the specifics of the Bancor protocol, a much smaller solution could suffice: do a commit-reveal with a penalty for non-revealing in Bancor tokens themselves. Basically, whenever someone commits a hash of a trade and doesn’t reveal, a percentage of both their Bancor and ERC-20 Ethereum tokens is burned (note that it works irrespective of the direction of the trade, thus revealing no information). If designed with careful attention to detail (for example, making sure that reveals are only accepted for commits in a previous block), this can fully solve the front-running problem, including front-running by miners.</p><p>Of course, even the simplified scheme is so complicated that almost no one would want to perform it by hand in MyEtherWallet. As the ecosystem grows, more sophisticated client programs (like the auto-trader we just implemented, or the commit-reveal client) would have to take that role on behalf of the users. Again: people aren’t sending their own Telnet requests every time they want to browse the Web, so why should the crypto world be any different?</p><h3>Acknowledgements</h3><p>This project started in collaboration with <a href="http://haseebq.com/">Haseeb Qureshi</a> and <a href="https://medium.com/@preethikasireddy">Preethi Kasireddy</a> at the <a href="http://www.initc3.org/events/2017-07-13-IC3-Ethereum-Crypto-Boot-Camp-at-Cornell-University.html">IC3 Ethereum bootcamp</a> under guidance from <a href="http://www.arijuels.com/">Ari Juels</a>, <a href="http://www.cs.cornell.edu/~iddo/">Iddo Bentov</a> and <a href="https://pdaian.com/">Phil Daian</a>. The post was rewritten considerably with massive help from Haseeb and <a href="http://nadertheory.com/">Nader Al-Naji</a>, who is about to take over the world with <a href="https://www.basis.io/">Basis</a>.</p><p>A disclaimer just in case: this is a personal project and it does not represent my employer or anyone else’s opinions. Since I worked on it in my spare weekends, the timeline ended up being very protracted, and I hope the attentive readers will forgive some small discrepancies (the Ethereum price may oscillate across the post, and some Bancor contract addresses had to be updated).</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d5e2bfd0d798" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>