<?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 Shane Auerbach on Medium]]></title>
        <description><![CDATA[Stories by Shane Auerbach on Medium]]></description>
        <link>https://medium.com/@shaneauerbach?source=rss-6fbda192024e------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*E3tCnfg7dZQBOSkbCK6HnQ.jpeg</url>
            <title>Stories by Shane Auerbach on Medium</title>
            <link>https://medium.com/@shaneauerbach?source=rss-6fbda192024e------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 01:22:40 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@shaneauerbach/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[Announcing contract interaction on evm.storage]]></title>
            <link>https://blog.smlxl.io/announcing-contract-interaction-on-evm-storage-ed0115b6d7b3?source=rss-6fbda192024e------2</link>
            <guid isPermaLink="false">https://medium.com/p/ed0115b6d7b3</guid>
            <category><![CDATA[transactions]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[smart-contracts]]></category>
            <category><![CDATA[blockchain]]></category>
            <dc:creator><![CDATA[Shane Auerbach]]></dc:creator>
            <pubDate>Wed, 29 Nov 2023 20:17:12 GMT</pubDate>
            <atom:updated>2023-12-20T20:30:13.380Z</atom:updated>
            <content:encoded><![CDATA[<h3>You can now interact with contracts and simulate transactions on evm.storage</h3><p>We recently added two exciting new features to evm.storage: <a href="https://blog.smlxl.io/announcing-transaction-traces-on-evm-storage-3a4e66e312fc">transaction traces</a> and <a href="https://blog.smlxl.io/announcing-bytecode-generated-storage-layouts-on-evm-storage-96761758d397">bytecode-generated storage layouts</a>. Today, we’re announcing another: our new ABI component, enabling interaction with contracts.</p><p>To explore how it works, let’s use the same example Alanna used in <a href="https://blog.smlxl.io/announcing-transaction-traces-on-evm-storage-3a4e66e312fc">her post announcing transaction traces</a>: a user provides ~13 USDC and 0.01 ETH to the Uniswap V2: USDC liquidity pool. Here’s <a href="https://evm.storage/eth/0x9557b6d8f6de42a77fa4f92787b60c7f880d4e3a526392ab3c051bac2fa60a7e">the transaction page</a>. Let’s explore more about this interaction with the new ABI component.</p><h3>ABI objects tab</h3><p>Navigating to the receiving contract, <a href="https://evm.storage/eth/latest/0x7a250d5630b4cf539739df2c5dacb4c659f2488d">UniswapV2Router02</a>, the first thing you’ll notice is that our storage component only serves a raw view, and all of the values in the slots are zero. This is true for many router contracts: their storage is simply unused — instead, they route interactions to other contracts where the state is updated accordingly. But router contracts are still very interesting as their ABIs show all of the possible interactions a user can pursue.</p><p>You can see our new ABI component at the bottom of the contract page. The main/default tab is called ABI objects, and it contains the following:</p><ol><li>Getter functions with values resolved per the user-defined block state of the contract page</li><li>Read-only functions</li><li>State-modifying functions</li><li>Events</li><li>Constructor</li><li>Fallback and receive</li><li>Custom errors</li></ol><p>These are all derived from the contract’s ABI. We currently only offer this component for verified contracts, but will add support for unverified contracts soon.</p><p>One of the functions you’ll find in the state-modifying section is addLiquidityETH, which was the method called in the sample transaction.</p><h3>Function-specific tabs</h3><p>If you want to interact with a contract via the functions, you can click into any of the read-only or state-modifying functions to open an input form. Let’s look further into addLiquidityETH.</p><p>Interacting with complex contracts via forms is a bit painful when there are many arguments. We’ve done our best to make it as easy as possible with the UI, showing the label and type for each argument and offering validation. But, realistically, you’re probably going to want to cheat with our <em>Generate Template</em> feature. Here I’ve entered the transaction hash of the <a href="https://evm.storage/eth/0x9557b6d8f6de42a77fa4f92787b60c7f880d4e3a526392ab3c051bac2fa60a7e">sample transaction</a> to prepopulate all of the fields from it. I could have also used the <em>Generate Template</em> feature without supplying a transaction hash, and it would have used the most recent transaction for which addLiquidityETH was the method.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*udBK9lWdOXPRcKIYMsDCJQ.png" /><figcaption>The addLiquidityETH input form</figcaption></figure><h3>Transaction simulation</h3><p>You may have noticed that below the arguments we have simulation inputs. These were also populated for us by the <em>Generate Template</em> feature to replicate the conditions of the original transaction.</p><p>You can change any of the function or simulation inputs to simulate counterfactual transactions. A few things to try:</p><ol><li>Change gas from 218883 to 160000 and simulate. You’ll see that the simulated transaction reverts. The original transaction used 161109 gas, so this runs out of gas.</li><li>Change to to a different address and simulate. If the sender had wanted, they could have redirected the LP token (Uniswap V2) to a different wallet.</li><li>Change amountTokenDesired to a very large number. The simulated transaction still succeeds and has the same outcomes, because it was still able to honor amountTokenMin.</li></ol><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F889636134%3Fapp_id%3D122963&amp;dntp=1&amp;display_name=Vimeo&amp;url=https%3A%2F%2Fvimeo.com%2F889636134&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F1761335710-cf701502cb3963077346696b9ff8e127cc40f7eca3cbeea3145fcf8eaabe7895-d_1280&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=vimeo" width="1920" height="1135" frameborder="0" scrolling="no"><a href="https://medium.com/media/46b983f382bf3fce00ff0db1f1c8a3ad/href">https://medium.com/media/46b983f382bf3fce00ff0db1f1c8a3ad/href</a></iframe><p>Most importantly, for any valid simulation, you can click <em>View Traces</em> to see a full transaction page for the simulated transaction, with all the features we have for actual transactions. You can even share the URL for most simulated transactions with others — here’s <a href="https://evm.storage/simulation/transaction/1f8b0800000000000013e360143873673fbb540393d25f460e0e2196c80c7d06295676ed9b99fb149ad7f16a89718954a9f286196c391f3cddf2be4eec9a2dc7223f79f41ab12bb77dca3fc8c0607584f133eb75490624b06047e6c4638add66072fcef5d29bb7e19c19db6b0f067ce0706f055ef943933571ca2947563c6f7e8022947a788bf31493fdac562b8fae0ea9caaf2bd1ceb88fcff864579776074625a04fb1e9d4b000004cc6a03b24010000/0xa4cf991b61553ba81b75ede8348ca15e7ae86d1544d4d639e351fbc80c6281d6">one</a> I created.</p><p>We shared some simple examples above, but we’re more excited to see how you use it. Some ideas:</p><ol><li>Before you’re executing a transaction, simulate it to make sure you’re happy with the outcomes, e.g., get an estimate of slippage in a swap transaction.</li><li>Take more control of your blockchain activity by constructing transactions yourself, relying less on dApps.</li><li>Take a transaction that reverts and simulate it with different inputs to work out how to get it to succeed.</li><li>Use it for security analysis: simulate potential attack vectors to make sure your contract isn’t at risk.</li></ol><h3>What’s next?</h3><p>We already have some ideas to further improve contract interactions:</p><ol><li><strong>Unverified contract coverage</strong>: We’re working on making it easier for you to interact with unverified contracts.</li><li><strong>State overrides</strong>: Perform a simulation with counterfactual contract state.</li><li><strong>Generating templates from internal transactions</strong>: You’ll find that we don’t have templates available right now for some functions that are only used in internal transactions, particularly read-only functions. With a bit of work, we can supply templates for these from internal transactions.</li><li><strong>Executing transactions</strong>: We want you to be able to connect your wallet and execute a transaction directly from evm.storage.</li></ol><p>We also plan on offering simulation as a service/SDK for users who want to simulate large volumes of transactions programmatically. If you’re interested in this, please reach out.</p><p>As always, if you have any questions or feedback, get in touch via <a href="https://t.me/+c0fPe4sYCKMwNzYx">our Telegram group</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ed0115b6d7b3" width="1" height="1" alt=""><hr><p><a href="https://blog.smlxl.io/announcing-contract-interaction-on-evm-storage-ed0115b6d7b3">Announcing contract interaction on evm.storage</a> was originally published in <a href="https://blog.smlxl.io/">smlXL</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Ethereum apocrypha]]></title>
            <link>https://blog.smlxl.io/ethereum-apocrypha-46e155e21a26?source=rss-6fbda192024e------2</link>
            <guid isPermaLink="false">https://medium.com/p/46e155e21a26</guid>
            <category><![CDATA[bytecode]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[smart-contracts]]></category>
            <category><![CDATA[solidity]]></category>
            <category><![CDATA[ethereum]]></category>
            <dc:creator><![CDATA[Shane Auerbach]]></dc:creator>
            <pubDate>Tue, 29 Aug 2023 16:29:23 GMT</pubDate>
            <atom:updated>2023-08-30T17:00:30.296Z</atom:updated>
            <content:encoded><![CDATA[<h3>Ethereum Apocrypha</h3><p>Working on <a href="http://evm.storage/">evm.storage</a>, we often stumble upon unique and interesting contract designs. If it can be done, someone has probably tried to do it. We think that’s a wonderful feature of decentralized blockchains, even if it sometimes causes us implementation headaches. In this post, we’ll share a few surprises that we’ve encountered:</p><p><strong>· </strong><a href="#97e9"><strong>A “big” contract</strong></a><strong><br>· </strong><a href="#c791"><strong>Many proxies → one implementation</strong></a><strong><br>· </strong><a href="#7838"><strong>One proxy → many implementations</strong></a><strong><br>· </strong><a href="#bc23"><strong>Overlapping layouts</strong></a><strong><br>· </strong><a href="#2ca3"><strong>Deeply nested variables</strong></a></p><h3>A “big” contract</h3><p><a href="https://evm.storage/eth/latest/0x06450dee7fd2fb8e39061434babcfc05599a6fb8">XENCrypto</a>’s interesting primarily because it’s big. Our data shows it has over 190MM storage writes! You’d think that this would suggest the token had many holders, but we find only 303K keys in <a href="https://evm.storage/eth/latest/0x06450dee7fd2fb8e39061434babcfc05599a6fb8/_balances#map">_balances</a> and 54K in <a href="https://evm.storage/eth/latest/0x06450dee7fd2fb8e39061434babcfc05599a6fb8/_allowances#map">_allowances</a> have even been written.</p><p>So why is it so big? There’s a hint in how they define the project: “XEN Crypto is a social mining project… XEN is categorized as a Proof-of-Participation (PoP) cryptocurrency.”</p><p>Diving into the data, we see over 10MM keys (!) used in the <a href="https://evm.storage/eth/latest/0x06450dee7fd2fb8e39061434babcfc05599a6fb8/userMints">userMints</a> mapping. Each value in that mapping is a struct XENCrypto.MintInfo that requires 6 slots, so we have 60MM slots associated in total. Some of those userMints contain members whose values are zero (<a href="https://evm.storage/eth/latest/0x06450dee7fd2fb8e39061434babcfc05599a6fb8/userMints.0x0000000000f6b28110192be56ce7a4a9c75c79eb#map">an example</a>).</p><figure><img alt="The userMints page for XenCrypto on evm.storage" src="https://cdn-images-1.medium.com/max/1024/1*zVevdEVKp7dOAD3DuULJlA.png" /><figcaption>Each MintInfo struct in the userMints mapping occupies 6 slots. Imagine 10MM of these!</figcaption></figure><p>What’s the mechanism driving this high volume of mints? Free mints! Except for gas, mind you. Anyone with a wallet can submit a transaction to start minting Xen. The user defines a term in days and can claim their minted tokens at the end of the term. The amount a user receives is increasing in the number of days and decreasing in the number of other users minting over the same period.</p><p>For completeness, we also see almost 20K keys used in <a href="https://evm.storage/eth/latest/0x06450dee7fd2fb8e39061434babcfc05599a6fb8/userStakes#map">userStakes</a> and a further 5K used in <a href="https://evm.storage/eth/latest/0x06450dee7fd2fb8e39061434babcfc05599a6fb8/userBurns#map">userBurns</a>.</p><p><a href="https://www.coingecko.com/learn/what-is-xen-crypto">CoinGecko reports</a> that XENCrypto at one point was using up almost half of Ethereum block space, with its resulting gas price impact contributing significantly to Ether becoming a deflationary currency! Apparently now <a href="https://twitter.com/ercwl/status/1696015780192592239">it’s on Base</a>! Despite all of this, XENCrypto posed no issues for our infrastructure.</p><p>Incidentally, if you liked the data about the number of keys in a mapping, join <a href="https://t.me/+zw0fuNoYg39hZWRh">our Telegram group</a> and yell at us to put mapping key counts in the product. We haven’t prioritized it yet — I beg our engineering team for it every cycle but nobody listens to me.</p><h3>Many proxies → one implementation</h3><p><a href="https://www.ambisafe.com/">Ambisafe</a> is a blockchain infra provider, and their work includes smart-contract wallets: <a href="https://evm.storage/eth/latest/0x0bdc989f692fad900c8c880af2e8979e601861d0">0x0b…d0</a> is an unverified proxy contract with unverified implementation <a href="https://evm.storage/eth/latest/0xc3b2ae46792547a96b9f84405e36d0e07edcd05c">0xc3…5c</a>. Here’s what’s remarkable: we detect that <a href="https://evm.storage/eth/latest/0xc3b2ae46792547a96b9f84405e36d0e07edcd05c">0xc3…5c</a> is the implementation address for over 545K proxy contracts! And there’s another Ambisafe-deployed implementation contract, <a href="https://evm.storage/eth/latest/0x072461a5e18f444b1cf2e8dde6dfb1af39197316">0x07…16</a>, that has 540K associated proxy contracts.</p><figure><img alt="A diagram showing 545K proxies DELEGATECALLing into a single implementation contract." src="https://cdn-images-1.medium.com/max/1024/1*45o9flP8YjzvdckRmDC9NA.png" /><figcaption>545K proxy contracts share a single implementation.</figcaption></figure><p>Without knowing much about their implementation, at a high level it makes a lot of sense to allow users to deploy smart-contract wallets that get all of their logic via DELEGATECALLs into a shared implementation contract.</p><p>This Ambisafe pattern caused us minor hardship in building <a href="http://evm.storage/">evm.storage</a>. We identify proxy-implementation pairs through DELEGATECALLs. We define the implementation contract’s relevant range by the first and last encountered DELEGATECALLs. We chose this approach because it doesn’t require contracts to be verified or assume that an implementation contract’s address is written in a specific slot within the proxy’s storage (related: <a href="https://eips.ethereum.org/EIPS/eip-1967">ERC-1967</a>).</p><p>When we started working on proxy coverage, we were mostly thinking about it as an approach to upgradeability. In that setting, each implementation is typically associated with a single proxy, and a proxy may be associated with a handful of implementations as the developer updates the logic across several versions.</p><p>But another common pattern is using proxies for gas optimization. If you want to execute the same logic across many contracts, it’s efficient to deploy that logic in a single implementation contract and then DELEGATECALL to it from many proxies, as we see with Ambisafe. This broke our initial approach to tracking pairs as our processes bogged down in constantly loading large lists from DB to memory, processing duplicate checks, and writing them back. Switching to a linked list structure to maintain the relationships allowed us to better scale across these many-to-one relationships.</p><h3>One proxy → many implementations</h3><figure><img alt="A diagram showing a single proxy calling 415 implementation contracts" src="https://cdn-images-1.medium.com/max/1024/1*cMtolzcf8yZ2BFfQb7oWtQ.png" /><figcaption>A very social MEV Bot. I wish I had that many friends.</figcaption></figure><p>Ambisafe had the implementation with the most proxies. What’s the proxy with the most implementations? Our data suggests it’s this <a href="https://evm.storage/eth/latest/0xa69babef1ca67a37ffaf7a485dfff3382056e78c">MEV Bot</a>, with 418 associated implementation contracts (<a href="https://evm.storage/eth/latest/0x008b4d7cd96587e0209b79642e793345324530fe">e.g.</a>). Note that I’m just counting distinct DELEGATECALLees — these likely don’t represent standard proxy-implementation relationships. Thirteen of them had implementation ranges of less than ten blocks.</p><p>[Edit: <a href="https://medium.com/u/2a64f901e4fe">banteg</a> pointed out that this contract could be some variant of the <a href="https://github.com/dapphub/ds-proxy">ds-proxy family</a>, popularized by MakerDAO. We did some static analysis to confirm. It’s not a direct copy as it was compiled with a newer solc version (0.8.9) and contains some functions not found in the original:</p><pre>{<br>    &quot;1cff79cd&quot;: &quot;execute(address,bytes)&quot;,<br>    &quot;1f6a1eb9&quot;: &quot;execute(bytes,bytes)&quot;,<br>    &quot;60c7d295&quot;: &quot;cache()&quot;,<br>    &quot;65fae35e&quot;: &quot;rely(address)&quot;,<br>    &quot;78e111f6&quot;: &quot;Unresolved&quot;,<br>    &quot;948f5076&quot;: &quot;setCache(address)&quot;,<br>    &quot;97645e37&quot;: &quot;Unresolved&quot;,<br>    &quot;9c52a7f1&quot;: &quot;deny(address)&quot;,<br>    &quot;a90e8731&quot;: &quot;Unresolved&quot;,<br>    &quot;bf353dbb&quot;: &quot;wards(address)&quot;,<br>    &quot;c9892a5f&quot;: &quot;Unresolved&quot;<br>}</pre><p>But it definitely appears to be some variant. Thanks!]</p><p>Right now there’s not much more that we can say given that the contracts are unverified, but we’re working on generating storage layouts directly from bytecode, which will provide more visibility. Here’s a teaser:</p><figure><img alt="An image of an unreleased feature for evm.storage that shows an inferred storage layout for an unverified contract." src="https://cdn-images-1.medium.com/max/1024/1*N2g2yKjHz81WUHXdZX3t5w.png" /><figcaption>Inferred storage layouts, coming soon to unverified contract pages near you!</figcaption></figure><p>One thing we do see is that the relevant ranges for the implementation contracts are overlapping, meaning that the proxy is delegating logic to multiple implementations at once. This logic also features in <a href="https://eips.ethereum.org/EIPS/eip-2535">ERC-2535: Diamonds, Multi-Facet Proxy</a>. The idea is that a given proxy contract (a “diamond”) may use logic in multiple implementation contracts (“facets”), each of which is responsible for a separable part of the logic and set of slots on the proxy’s storage.</p><p>We currently only index proxy-implementation pairs based on their block ranges, i.e., the duration from the first block in which we observe a DELEGATECALL to the last. To provide complete coverage for Diamonds, we’ll also need to record the relevant slots for each. We’re planning this work but haven’t started.</p><h3>Overlapping layouts</h3><p>One common pattern we see with non-empty proxy layouts is that the proxy’s layout is identical to the implementation’s (e.g., <a href="https://evm.storage/eth/latest/0xdbb0965046e142b4306ac453c7700bf768d6ac33">PositionToken</a>). We’re thinking of adding some visual affordance to make it clear which layout each entry in the unified storage map (and table) is coming from. Right now it might look like duplicate data in these cases.</p><p>A similar pattern is to have one layout contain explicit gap variables in the slots governed by the other contract’s layout, as we see with this <a href="https://evm.storage/eth/latest/0x6110d61dd1133b0f845f1025d6678cd22a11a2fe">Spice Finance proxy</a>. Another “feature” we discovered is that a single contract can assign the same name to different variables so long as they’re in different scopes, so you can have many of these identical gap variables.</p><p>We’ve also found some more creative usage. <a href="https://evm.storage/eth/latest/0xe28d9b24adc19809e595bd2370dcac55751c46a3">EternalStorageProxy </a>puts an address for _upgradeabilityOwner in the 0x00…00 slot even though its implementation uses the same slot for a mapping. This overloading works because the value actually used in the slot of the mapping is meaningless; typically it’s left as zeroes, but there’s no reason it can’t serve another purpose. They do a similar trick in slots 0x00…03 through 0x00…05, except in these cases the proxy and implementation agree that it’s a mapping but disagree on what mapping it is. Of course, this could cause collisions if any key is used in both mappings.</p><figure><img alt="A screenshot of overlapping storage layouts on evm.storage" src="https://cdn-images-1.medium.com/max/1024/1*WCuWHI__tnLkmrNjIyx46A.png" /><figcaption>One man’s uintStorage is another’s bytesStorage.</figcaption></figure><h3>Deeply nested variables</h3><p>This is not apocrypha, per se, as we frequently come across examples like these, but we love deeply nested variables! Check out <a href="https://evm.storage/eth/latest/0x000000000022d473030f116ddee9f6b43ac78ba3/allowance#map">allowance on Uniswap’s Permit 2</a>: a triple-nested mapping with a three-member struct at the end of the rainbow! Gorgeous!</p><figure><img alt="An evm.storage screenshot of the type of allowance on Permit2" src="https://cdn-images-1.medium.com/max/944/1*XSK2jkwwbvGXpQGF7HWPjA.png" /><figcaption>Nest those mappings!</figcaption></figure><p><em>Cheers to the smlXL colleagues (and @banteg) who helped with this post. Curses upon those that keep refusing to prioritize mapping key counts.</em></p><figure><img alt="It’s just a plain pink background in smlXL colors. Nothing to see here." src="https://cdn-images-1.medium.com/max/1024/1*fAAEy7h4-QJsDdE9fZlIWQ.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=46e155e21a26" width="1" height="1" alt=""><hr><p><a href="https://blog.smlxl.io/ethereum-apocrypha-46e155e21a26">Ethereum apocrypha</a> was originally published in <a href="https://blog.smlxl.io/">smlXL</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[annnddd it’s gone]]></title>
            <link>https://medium.com/@shaneauerbach/annnddd-its-gone-f1a663766f4f?source=rss-6fbda192024e------2</link>
            <guid isPermaLink="false">https://medium.com/p/f1a663766f4f</guid>
            <category><![CDATA[banking]]></category>
            <category><![CDATA[fdic]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[svb]]></category>
            <dc:creator><![CDATA[Shane Auerbach]]></dc:creator>
            <pubDate>Sun, 12 Mar 2023 01:23:41 GMT</pubDate>
            <atom:updated>2023-03-23T04:11:36.548Z</atom:updated>
            <content:encoded><![CDATA[<p>Don’t worry, <a href="https://www.linkedin.com/feed/update/urn:li:activity:7040159584518307840/">smlXL is OK</a>! But I participated in a bank run. I lost. Now I have some feelings…</p><h3><strong>What happened?</strong></h3><p>(If you actually don’t yet know what happened to SVB, read <a href="https://www.bloomberg.com/opinion/articles/2023-03-10/startup-bank-had-a-startup-bank-run">Matt Levine’s piece</a>.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/740/0*U1l8yrD0gd7dY2g1" /><figcaption>They put out a bat signal for “mediocre white guy looking concerned” and I hurried right over. (Courtesy of Justin Sullivan | Getty Images*)</figcaption></figure><p>Driving down to SVB’s headquarters in Santa Clara on Friday morning, I couldn’t rid my mind of <a href="https://www.youtube.com/watch?v=Y3AM00DH0Zo">that South Park meme</a>. Our CEO, <a href="https://www.linkedin.com/in/dor-smlxl/">Dor</a>, had asked me to go to a branch to see if they were able to write cashier’s checks or had info on our pending transfers. We’re a small startup. A big chunk of our operating capital was in SVB. Dor had already tried at a branch in New York, <a href="https://www.newcomer.co/p/police-respond-to-founders-gathered">to little avail</a>.</p><p>We both knew the trip was futile. The California Department of Financial Protection and Innovation had already closed SVB and appointed the Federal Deposit Insurance Corporation (FDIC) as receiver. The <a href="https://www.fdic.gov/news/press-releases/2023/pr23016.html">FDIC’s press release</a> had plenty of ambiguity, but it was clear that the bank was closed.</p><p>I wanted to try for three reasons: I like my job and my colleagues, and I wanted to do <em>something</em>. I don’t trust America: it wouldn’t really have surprised me if there was some special back door for well connected depositors to get their funds out of a closed bank. What better place to find it than at the HQ, in Silicon Valley? And I went out of morbid curiosity–what would it look like?</p><p>The answer: not much. When I arrived, there were about a dozen customers like myself, hoping, against their better judgment, that they might find some assistance. There were a few photographers and journalists. The lights were on inside but the doors were locked, a lone person at the front desk mostly avoiding eye contact. The FDIC press release was taped to the door.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*au_EhgbWpEQT_18x" /><figcaption>“Are you bringing money in or taking it out?”</figcaption></figure><p>The absurdist highlight was the arrival of the Brink’s truck. We all took photos, media and customers alike. As the driver went in, someone asked him if he was bringing money in or taking it out.</p><p>I chatted with a few friendly founders. We exchanged commiserations. But that was about the extent of it. And, yes, Justin Sullivan of Getty Images took a photo of me, shown above, that ended up in stories for <a href="https://www.npr.org/2023/03/10/1162599556/silicon-valley-bank-collapse-failure-fdic-regulators-run-on-bank">NPR</a> and <a href="https://www.cnbc.com/2023/03/10/silicon-valley-bank-collapse-how-it-happened.html">CNBC</a>. I was initially mortified by this — I never consented! — but it is pretty funny, and I presume he’s not required to get consent, was just doing his job. My mom said I look like SBF — that’s the worst part.</p><h3>What is to be done?</h3><p>The section title is an intentional albeit imprecise (perhaps asinine) literary reference. I’ll lay out my utopian ideas à la Chernyshevsky, although you’ll see my mood is better represented by Doestoevsky’s <em>Underground Man</em>’s sense of disaffection and futility.</p><h4>FDIC insurance should be uncapped</h4><p>Let’s start with the basics of banking: <a href="https://www.youtube.com/watch?v=Y3AM00DH0Zo">Stan</a> had it coming. Stan didn’t object when the banker put the $100 check his grandmother had given him into a money market mutual fund. He didn’t even object when the banker reinvested the earnings into foreign currency accounts with compounding interest! Stan pursued a risky investment strategy and it didn’t work. It’s gone! If we gave Stan his $100 back, he’d be incentivized to pursue risky strategies in the future, pocketing the rewards when it goes well and getting bailed out when it doesn’t. That’s moral hazard!</p><p>But Stan’s experiences are meaningfully different than those of SVB depositors. SVB depositors have lost access to funds sitting in checking accounts designated for operational purposes like payroll. These were <em>deposits</em>, not <em>investments</em>. (Ironically, one founder I met at SVB said he believed customers with money in SVB money market funds would be fine because SVB was only facilitating those products and the money was held by other banks.) Why must depositors be exposed to this risk?</p><p>Let’s try the moral hazard argument: uninsured depositors must face losses when a bank fails because this incentivizes depositors to use healthier banks that are less likely to fail, thereby reducing systemic risk. As <a href="https://twitter.com/BillAckman/status/1634564398919368704">Bill Ackman points out</a>, this puts the onus of evaluating banks’ creditworthiness on each individual depositor. The best demonstration that this doesn’t work is what’s just happened with SVB. We had a lot of money there because we perceived it as safe relative to alternatives. <a href="https://www.axios.com/2023/03/11/silicon-valley-bank-roku-roblox-impacted">Apparently Roku, Roblox, and many others felt similarly</a>.</p><p>You could argue depositors were careless for concentrating funds in few accounts and in sizes beyond the FDIC insurance cap of $250K. Fortunately for us, Dor spread out smlXL’s operational funding enough that we have no immediate operational concerns. But Garry Tan estimates that <a href="https://twitter.com/garrytan/status/1634630941334470656">30% of SVB depositors will fail to make payroll in the next 30 days</a>. I suspect that’s inflated, and it’s easy to laugh at silly startups suffering from irresponsible financial management (see below), but were they crazy to consider their deposits safe? When was the last time uninsured depositors actually lost funds? No, genuinely, I’m asking you. I spent 30 minutes Googling it. ChatGPT tells me it was when depositors of Guaranty Bank in Wisconsin lost about a million in 2017, but the <a href="https://www.fdic.gov/resources/resolutions/bank-failures/failed-bank-list/guaranty.html">FDIC says those were converted into deposits at First-Citizens</a>. In this disorienting week, the only solace I take is that ChatGPT is <em>still</em> lying confidently to me.</p><p>To the point: <strong>remove the $250K limit on FDIC insurance</strong>. It’s actually free to do this in two important ways:</p><p>First, we’re going to commit to regulating banks in the future properly such that these failures never happen. Right?</p><p>Second, I’m here to announce that I’m partnering with <a href="https://nypost.com/2022/04/08/bucks-star-giannis-antetokounmpo-has-money-in-50-bank-accounts/">my technical cofounder Giannis Antetokounmpo</a> to launch a new startup focused on checking account abstraction–you thought this <a href="https://ethereum.org/ca/roadmap/account-abstraction/">only mattered for Ethereum</a>?! You’ll log in to Giannis Bank and see a checking account with millions in funding. Underneath the hood we’ll have that parceled up into as many FDIC-insured $250K chunks held at actual banks as required. We’ll do it. We’ll build a fully FDIC-insured synthetic checking account with no limits. If you don’t want me extracting rent from this nonsense, and I swear on my tech worker identity that I will find ways to unreasonably enrich myself, let’s just acknowledge that the $250K limit applied on an account level is arbitrary and capricious. That’s legalese for dumb.</p><p>Once we’re not holding depositors responsible for bank creditworthiness, who should take that responsibility? I don’t know… Maybe the OCC or the FDIC? What’s Gary Gensler up to nowadays? Is he busy?</p><h4><strong>No bailouts, unless *I* really need one</strong></h4><p>We’ll never have this problem again now that we fixed the FDIC. But what about the bailout that Tan, Ackman, and others are advocating? More precisely, they want SVB depositors to be made whole, quickly, and they’re quite pointedly arguing this would be the government acting on behalf of depositors to make them whole and avoid contagion, not a bank bailout. Rough day for SVB equity holders — nobody’s standing up for them!</p><p>You have to be really careful with positionality when making appeals to “fairness.” Sure, I agree on the surface with Tan that it’s unfair that some startups will fail based solely on the bank in which they deposited their capital, a random cull imposed on a generation of innovators. But, and I’m sorry in advance for being flippant, there’s part of me that responds as follows:</p><blockquote>Boohoo for them. Silicon Valley is already random. What’s a little more? Who’s to say whether this is actually good or bad for overall innovation? Isn’t it also true that making depositors whole would constitute a massive transfer to the same VCs that contributed to the bank run by telling their portfolio companies to get out early? Was <strong><em>that</em></strong> fair? To what degree is this profiteering via scaremongering?</blockquote><p>This is my visceral response even though <em>I</em> would benefit from depositors being made whole. I am them. Boohoo for me. I can’t imagine how the rest of America must feel about this prospect of the FDIC going out of its way to serve the generally very privileged customers of Silicon Valley Bank.</p><p>I am sincerely sorry if you’re reading this and you’re worried about whether you’ll make payroll or receive your paycheck next cycle. I don’t mean to trivialize or mock the very real consequences — I’m trying to reflect on perceptions.</p><p>However you may feel about what constitutes fair in this context, the bottom line is that as uninsured depositors, we’re not legally entitled to much at all beyond relatively preferred status in the long line of SVB’s creditors.</p><p><strong>So what should happen now?</strong></p><p>Let’s see if the FDIC can work out how to make depositors materially whole, preferably soon, without too much special treatment. Unlike Stan’s case, it’s not actually gone. We presume it’s not all gone. Right?</p><p>First, end the bank run, as they did overnight Thu/Fri. Perhaps they should’ve acted more quickly — <a href="https://www.axios.com/2023/03/11/the-largest-bank-run-in-history">$42 billion escaped amid rumors on Thursday</a> — but that also may be more the discretion of the California Department of Financial Protection and Innovation than the FDIC. It’s also an incredibly important decision and one that you’d want to analyze very carefully. I find it hard to fault the timing. I presume they can’t claw back withdrawals made on Thursday? If they can, they should — those withdrawals are precisely as legitimate as those that failed to go through on Friday.</p><p>Next, fulfill your obligations to insured depositors. If the FDIC loses credibility, ruh roh. The FDIC promised in <a href="https://www.fdic.gov/news/press-releases/2023/pr23016.html">the press release</a> that “all insured depositors will have full access to their insured deposits no later than Monday morning.” Thinking about the logistics of this, I find it remarkable.</p><p>Finally, how can they do right by uninsured depositors and other creditors? Their toll-free hotline is active right now, over the weekend, and <em>those damn bureaucrats</em> are diligently working away at making sure they have correct records for uninsured depositors. The obvious next step is as follows: “Uninsured depositors will receive a receivership certificate for the remaining amount of their uninsured funds.” But the more important part is in the preceding sentence: “The FDIC will pay uninsured depositors an advance dividend within the next week.” They know depositors need to access these funds in the near term and they’re issuing an advance to try to accommodate. Depending on the details, it’s this advance, presumably but not necessarily calculated as a percentage of the uninsured deposit, that will mitigate fears about startups not making payroll.</p><p>Three things I’ll be looking out for in the weeks and months ahead, assuming no buyer is found over the weekend:</p><ol><li>To what degree will next week’s advance make uninsured depositors whole? 80% would have drastically different outcomes than 20%.</li><li>To what degree and on what timeline will uninsured depositors be made whole eventually, via the receivership certificates?</li><li>How will the private sector accommodate startups with liquidity problems, perhaps by allowing them to trade or borrow against receivership certificates?</li></ol><p>And, yeah, if smlXL’s operations ever come under immediate threat because of this nonsense, you’d better believe I’ll be crying to anybody who will listen for a rescue. I like my job. <strong>IT’S NOT FAIR!</strong></p><h3><strong>Stuff you put at the bottom of a blog post</strong></h3><p>These are my own views, not those of my employer, <a href="https://www.smlxl.io/">smlXL</a>. I didn’t want to comment too specifically about what this means for smlXL. Our CEO, Dor, has been transparent throughout. You can read more about how he experienced this (it’s pretty funny!) and what it means for us in his <a href="https://www.linkedin.com/feed/update/urn:li:activity:7040159584518307840/">LinkedIn post</a>. I also appreciate that he’s cool with me posting this — he even helped me by sharing some links.</p><p>I didn’t really edit this. I’m tired. If you see errors or have advice on how to make the post better, please email me at <a href="/service/mailto:shaneauerbach@gmail.com">shaneauerbach@gmail.com</a>. I’ll even acknowledge you here if you want.</p><p>I’m not sure if I’m allowed to use that image of me, taken by Justin/Getty, at the top. I’m going to ask for forgiveness rather than permission here. It is my likeness, right? At the very least it’d be a hilarious lawsuit! Anyway, Justin/Getty, if you want me to take it down, please pop me a cease and desist. I’ll chuck that in my “Fond Memories of the End Times” scrapbook and take the photo off this post. 🙂</p><h3>Updates</h3><ol><li>3/12 #1: Astute readers have pointed out that removing the FDIC cap <em>would not </em>be free because the two reasons I gave for why it would be free above are counterfactual. Good point! And it’s also true that you, noble depositor, would likely have to pay for the removal of the cap in some form, given that FDIC insurance is funded by the banks whose depositors are protected. Anybody have any idea how much it would cost and how it would be passed through? In any case, depositors perceive the checking account as a risk-free store of value. If providing said product is a little more costly than a store of value that’s risk-free almost all of the time, so be it. Let’s surface that cost. If that drives consumers away from banks to stablecoins and mattresses, then I’d argue that’s a reflection on banking as a modern technology.</li><li>3/12 #2: Guys in my fantasy football league have pointed out that Giannis Bank already exists in some form, with examples like <a href="https://www.intrafinetworkdeposits.com/how-it-works/">IntraFi</a> and <a href="https://www.maxmyinterest.com/">Max</a>. I’m very disappointed by this — Giannis promised to do the due diligence on this one.</li><li>3/13: We were bailed out, but don’t call it a bailout! But, shit, yeah, it’s a relief to hear that Dor has access to all the funds once more.</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f1a663766f4f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How Does Ethereum Manage Data?]]></title>
            <link>https://blog.smlxl.io/how-does-ethereum-manage-data-3ee85263134b?source=rss-6fbda192024e------2</link>
            <guid isPermaLink="false">https://medium.com/p/3ee85263134b</guid>
            <category><![CDATA[crypto]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[data]]></category>
            <dc:creator><![CDATA[Shane Auerbach]]></dc:creator>
            <pubDate>Mon, 28 Nov 2022 23:53:47 GMT</pubDate>
            <atom:updated>2022-12-06T22:50:48.032Z</atom:updated>
            <content:encoded><![CDATA[<p><em>We explore Ethereum data and the challenges in consuming it.</em></p><p>We start with a description of the Ethereum Virtual Machine and the state and non-state data it maintains. Then we cover challenges including interpreting compiled bytecode, observing contract-to-contract calls, and more.</p><p><a href="#1fb0"><strong>Understanding the Ethereum Virtual Machine (EVM)</strong></a><br> — <a href="#c6a3">What is the EVM?</a><br> — <a href="#1c63">How is EVM state maintained?</a><br> — <a href="#84a6">What non-state EVM data exists?</a></p><p><a href="#baa3"><strong>Challenges in using Ethereum data</strong></a><br> — <a href="#55c3">On-chain contract code is compiled bytecode</a><br> — <a href="#4b99">Contract source code is often private</a><br> — <a href="#c00a">Contracts call other contracts (and observability is poor)</a><br> — <a href="#7829">Contract code is no longer immutable</a><br> — <a href="#e494">Contract storage can be hard to explore</a><br> — <a href="#3c01">If it just happened, it might not have happened</a></p><p><a href="#b178"><strong>Conclusion</strong></a></p><h3>Understanding the Ethereum Virtual Machine (EVM)</h3><h4>What is the EVM?</h4><p>The Ethereum Virtual Machine (EVM) is sometimes referred to as a World Computer. Thousands of nodes <a href="https://www.ethernodes.org/countries">across the world</a> execute the same code to maintain the same state.</p><h4>How is EVM state maintained?</h4><p>Figure 1 illustrates EVM state management and data structures. We start from an arbitrary State <em>n-1</em> in which an instance of the EVM has three types of state data:</p><ol><li>Account balances (in ETH) and nonces. Figure 1 shows two addresses (<em>0xa5…37</em> and <em>0x93…af</em>), each with 5 ETH. Each address also has a nonce, not shown, which represents a count of its transactions.</li><li>Contract code. Figure 1 shows pseudocode for a simple contract, deployed at <em>0x93…af</em>, that maintains a storage variable <em>x</em> and increments it each time the account receives a transfer of at least 1 ETH.</li><li>Contract storage. Figure 1 shows contract storage for <em>0x93…af</em> as a dictionary of key-value pairs, including entry <em>x : 1.</em></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZHZ5U-denMdM_heoEAvpEQ.png" /><figcaption>Figure 1: An illustration of EVM blocks and state</figcaption></figure><p><strong>Let’s walk through an example</strong>. Account <em>0xa5…37</em> sends 1 ETH to the contract, <em>0x93…af</em>, and the submitted/pending transaction sits in the “mempool” until it is included in a block. The example transaction costs 0.1 ETH in gas. Part of this is burned, per<a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md"> EIP1559</a>. After a proposer creates <em>Block n</em>, validators verify that it is legitimate. The new block propagates across the network and receiving nodes then run the code triggered by the included transactions to update their state to <em>State n. </em>Because 1 ETH was received, <em>x</em> is incremented in storage from 1 to 2 and Event is emitted in the log of the receipt associated with the transaction. Going from state <em>n </em>to <em>n+1</em>, only 0.5 ETH is sent. The contract code runs but neither increments <em>x</em> nor emits the event because the <em>if</em> condition is not met.</p><p>We recommend <a href="https://medium.com/cybermiles/diving-into-ethereums-world-state-c893102030ed"><em>Diving into Ethereum’s world state</em></a> by Timothy McCallum and <a href="https://medium.com/hackernoon/getting-deep-into-ethereum-how-data-is-stored-in-ethereum-e3f669d96033"><em>Getting Deep Into Ethereum: How Data Is Stored In Ethereum?</em></a><em> </em>by vasa.</p><h4>What non-state EVM data exists?</h4><p><strong>Blocks contain transactions that cause state to change</strong>. It can be intuitive to think of a block like a diff used in git software, in that it records a set of changes. That being said, it’s a somewhat incomplete diff: a block only records the transactions that initiate the state changes, not the impact of executions on state, which may involve many <em>internal transactions </em>between contracts.</p><p><strong>EVM instances generate a receipt for each processed transaction</strong>. While receipts are off-chain and stored on each node, they are verifiable: a hash of each receipt is included in the block. The receipt, in turn, contains logs / events, which are data emitted by smart contracts called in transactions. In the example contract code, emit Event would create a log with the data designated by the smart contract.</p><p>We recommend <a href="https://ethereum.org/en/developers/docs/evm/">Ethereum.org’s EVM documentation</a>; <a href="https://consensys.net/blog/news/programmable-blockchains-in-context-ethereum-smart-contracts-and-the-world-computer/"><em>Ethereum, Smart Contracts, and the World Computer</em></a><em> </em>by ConsenSys; and the <a href="https://www.evm.codes/about?fork=byzantium"><em>About the EVM</em></a><em> </em>page at evm.codes.</p><h3>Challenges in using Ethereum data</h3><p>Ethereum is a public blockchain in the sense that anyone can run a node by running <a href="https://geth.ethereum.org/">geth</a> or an alternative client. New nodes catch up to current state by receiving blocks on the network and processing them in order.</p><p>One might expect that it would be easy to access and interpret all data on a public blockchain like Ethereum. Alas, it isn’t. Let’s explore how these distributed systems are complex.</p><h4>On-chain contract code is compiled bytecode</h4><p>Smart contract developers write readable code, often with rich commenting and specification like <a href="https://docs.soliditylang.org/en/v0.5.10/natspec-format.html">Natspec</a>, in languages like <a href="https://docs.soliditylang.org/en/v0.8.12/index.html">Solidity</a> (JS-like) and <a href="https://vyper.readthedocs.io/en/stable/">Vyper</a> (Pythonic). There are also lower-level options like <a href="https://docs.soliditylang.org/en/v0.8.9/yul.html">Yul</a>(+).</p><p>However, the smart contract code stored on the blockchain and executed on each node is compiled EVM bytecode, often represented in hexadecimal. While it’s executable, it can be difficult to interpret and/or decompile to understand the workings of a smart contract.</p><h4>Contract source code is often private</h4><p>A smart contract developer can choose to make their Solidity/Vyper/Yul contracts public by <a href="https://etherscan.io/address/0x5d2BF3b4264EFADE95fC89348f1367fCa0552861#code">submitting them to services like Etherscan</a>, which compile the submissions and check that the resulting bytecode matches what’s in the EVM state. But many developers will keep their smart contract source code private either because they see limited advantage in making it public or because they fear the source code could expose possible security issues or exploits.</p><p>Another contract source code object that may or may not be public is the <em>Application Binary Interface </em>(ABI), which tells other services how they may call a contract and how to interpret its events / logs. Without an ABI, it can be difficult to call a contract or interpret its logs. You may be able to guess at least a partial ABI for a contract: Identify its general purpose and assume its functions and events are the same as those for standard contract templates (e.g. ERC20, ERC721) for that purpose. Or you can use a function signature database like <a href="https://sig.eth.samczsun.com/">sig.eth.samczsun</a> or <a href="https://www.4byte.directory/">4byte.directory</a>. It may also be possible to infer parts of the ABI by analyzing disassembled bytecode (e.g. <a href="https://github.com/shazow/whatsabi">whatsabi</a>) if the bytecode was generated by a standard compiler. Here’s <a href="https://etherscan.io/address/0x4c51ee9d67c7d9684455e8cbfb75cac7962ec000#code">an example</a> of a contract written in Yul that was <a href="https://twitter.com/bertcmiller/status/1446416008709918732?t=YW06kB8OrNtPpQlq_HLCwA&amp;s=09">exploited for ~$1MM</a> by an attacker who reverse engineered the decompiled assembly to find an unused approve function without standard checks. In summary, you can call functions and interpret logs as long as you can work out the parts of the ABI that correspond to those functions and events.</p><h4>Contracts call other contracts (and observability is poor)</h4><p>Every smart contract computation on the EVM is kicked off by a signed transaction. Currently, only externally owned accounts (EoAs) can sign transactions. But a smart contract called by a transaction may call other contracts, which can in turn call others. These contract-to-contract calls are often referred to as <em>internal transactions</em>. Just about any moderately complex smart contract system will involve internal transactions.</p><p>One common use case for internal transactions is using proxies to enable upgradeability. If you want to allow your users to do some complex thing, but you also want to be able to upgrade / update / fix how that complex thing is executed, you can have users interact with a proxy contract that calls an implementation contract with the address written in the proxy’s storage. When you are ready to upgrade the implementation logic, deploy the upgraded implementation contract and then call the proxy to reset its stored pointer to the new contract. Figure 2 illustrates the idea.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*g0MMGo2FObzwCYMvmypapA.png" /><figcaption>Figure 2: Using a proxy pattern to allow upgradability in an implementation contract</figcaption></figure><p>There are a few variants of these designs: One can use a proxy purely as an updateable registry that forwards the user to another contract. An alternative approach is to use the DELEGATECALL pattern, in which code from the called contract is executed on the calling contract’s storage, allowing for updated functionality on the same state storage.</p><p>Critically, these <em>internal transactions</em> are not recorded explicitly in blocks. Recovering them requires using a <em>debug_traceTransaction</em> method or instrumenting a custom EVM client. The latter approach is employed by services like <a href="https://etherscan.io/">Etherscan</a> and <a href="https://tenderly.co/">Tenderly</a>.</p><p>We recommend <a href="https://medium.com/coinmonks/delegatecall-calling-another-contract-function-in-solidity-b579f804178c"><em>DelegateCall: Calling Another Contract Function in Solidity</em></a> by zeroFruit, and <a href="https://ethereum.stackexchange.com/questions/3417/how-to-get-contract-internal-transactions"><em>Accessing contract internal transactions</em></a> and <a href="https://ethereum.stackexchange.com/questions/4446/instrumenting-evm"><em>Instrumenting EVM</em></a><em> </em>on Ethereum Stack Exchange.</p><h4>Contract code is no longer immutable</h4><p>Ethereum’s original CREATE code deploys a contract to an address based upon a hash that includes the deployer address and their nonce, the count of transactions initiated by the account. Funds can be sent to a contract before or after it is deployed. Contract code and storage can be deleted, and the balance sent to a designated party if the SELFDESTRUCT instruction is called, but nothing can be redeployed at that address with CREATE because the original deployer’s nonce would have increased.</p><p>The Constantinople upgrade introduced CREATE2 to allow developers to deploy a contract at a deterministic address, so long as that address doesn’t already have deployed code. It is like CREATE in that it includes the deployer’s address in a hash for the deployment address, but different in that it replaces the deployer’s nonce with the initialization code of the contract and a user-selected seed (“salt”). CREATE contracts will never collide with CREATE2 contracts because of a domain separation: CREATE2 puts a 0xFF as the first byte input to the hash.</p><p>CREATE2 also enables “metamorphic contracts,” where the code at a given address can be changed. Figure 3 and the instructions below illustrate the logic:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Na10GmkDKN-VYPHz3w9mtA.png" /><figcaption>Figure 3: Altering code in a metamorphic contract</figcaption></figure><ol><li>Create a smart contract factory, i.e. a contract that creates and deploys contracts, to serve as your deployer for the metamorphic contract. Give that factory the ability to deploy a self-destructible metamorphic contract with CREATE2. The initialization code of the metamorphic contract created by the factory should instruct it to copy the code of an implementation contract whose address is specified in the factory’s storage.</li><li>Create implementation contract v1 with the code you want in the metamorphic contract. Put the address of implementation contract v1 in the factory’s storage. Use the smart contract factory to deploy the metamorphic contract, which will call the factory in its init to find the address of the implementation contract whose code it will copy with EXTCODECOPY.</li><li>When you wish to upgrade implementation, i.e. metamorphose the metamorphic contract: a) deploy the new logic in implementation contract v2, b) call SELFDESTRUCT in the metamorphic contract, c) replace the pointer from implementation contract v1 to v2 in the factory’s storage, d) redeploy the metamorphic contract with the factory. Because the deployer, initialization code, and salt remain unchanged, the new code from implementation contract v2 will be deployed at the same address as was used previously, achieving the metamorphosis.</li></ol><p>CREATE2 also has significant security implications: a user may be confident with the impact of their transaction with a certain contract address only to find that the code at the address has been updated. There is also some risk of this with proxy structures, but proxy structures are clearer / more detectable in that the user can, at least in theory, see them pointing to new upgrades.</p><p>You cannot even feel particularly safe with a contract that was created with CREATE. Call that Contract C and suppose it was created using CREATE by Contract B, which was in turn created with CREATE2 by Contract A. The owner of A can update B with SELFDESTRUCT and CREATE2, resetting its nonce in the process. B’s nonce can then be incremented up to where it was when C was created, and then C can be upgraded with SELFDESTRUCT and CREATE called by B. With these “cascaded resurrections,” you’re at some risk of unexpected contract upgrades if you’re interacting with any contract that is anywhere downstream of a contract that was created with CREATE2, which isn’t easy to detect.</p><p>These and other considerations motivate <a href="https://eips.ethereum.org/EIPS/eip-4758">EIP-4758</a>, a current proposal to deactivate SELFDESTRUCT by changing it to SENDALL, thereby allowing for recovery of funds without deleting code or storage. It is a candidate for inclusion in the <a href="https://ethereum-magicians.org/tag/shanghai-candidate">upcoming Shanghai fork</a> and there’s some fascinating discussion on the <a href="https://ethereum-magicians.org/t/eip-4758-deactivate-selfdestruct/8710">Ethereum Magicians forum</a>.</p><p>We recommend <a href="https://a16zcrypto.com/metamorphic-smart-contract-detector-tool/"><em>A Tool for Detecting Metamorphic Smart Contracts</em></a>, by Michael Blau; <a href="https://informationsecurity.uibk.ac.at/pdfs/FB-Ethereum-Create2.pdf"><em>Not all Code are Create2 Equal</em></a><em> </em>by Michael Fröwis and Rainer Böhme, <a href="https://0age.medium.com/the-promise-and-the-peril-of-metamorphic-contracts-9eb8b8413c5e"><em>The Promise and Peril of Metamorphic Contracts</em></a> by 0age, <a href="https://www.parity.io/blog/a-postmortem-on-the-parity-multi-sig-library-self-destruct/"><em>A Postmortem on the Parity Multi-Sig Library Self-Destruct</em></a><em> </em>by Parity Technologies, and <a href="https://medium.com/parity-hack-trace/parity-hack-and-153-037-stolen-eth-2a7704f59f3b"><em>Parity multisig hack resulting in 153,037 stolen ETH</em></a><em> </em>by Parity Hack Trace.</p><h4>Contract storage can be hard to explore</h4><p>Contract storage is a dictionary of key-value pairs. Slots are generally assigned to variables in the order that they appear in the contract code, with some nuance around dynamically-sized arrays, mappings, and type nesting. Even if you know the source code of the contract, you often can’t retrieve a complete version of the contract’s state by digging in storage unless you know exactly what you’re looking for. To interpret storage slots in proxy contracts, you need to know the source code of the implementation contract at the time of the storage change you’re interested in. If you don’t know the source code, you’re really going to be wandering blindly. A variable’s representation in storage depends on both its type and the high-level language’s compiler. For Solidity:</p><ul><li><strong>Fixed-size, single-valued variables</strong>:<strong> </strong>If the first two declared variables in a contract are single-valued and their sizes sum to greater than 32 bytes, they can be retrieved via RPC call to any Ethereum node with eth_getStorageAt(contract_address, 0x…0) and eth_getStorageAt(contract_address, 0x…1), respectively. Two variables with total size less than or equal to 32 bytes would be packed together in the first storage slot.</li><li><strong>Dynamically sized, single-valued variables: </strong><em>string</em> and <em>bytes</em> are not capped to the 256 bits of a single storage slot. If the length of the dynamically sized variable is less than or equal to 31 bytes, its value is packed together with its length in the storage slot: the value is stored in the higher-order bytes and <em>length * 2</em> is stored in the lowest-order byte. If the variable is 32 bytes or longer, then only <em>length * 2 + 1</em> is stored in the lowest-order byte of the slot, and the value itself is stored starting at <em>keccak256(storage_slot)</em> and spanning as many storage slots as required. The <em>* 2</em> and <em>* 2 + 1 </em>operations on the length are designed such that we know an even value represents a short variable that can be retrieved from the higher-order bytes of the same slot, whereas an odd value suggests that the variable’s value is stored starting at <em>keccak256(storage_slot)</em>.</li><li><strong>Multi-valued fixed-sized variables</strong>: Suppose the third declared variable is uint256[2]. Its two values can be found with keys <em>0x…2</em> and <em>0x…3</em>, respectively.</li><li><strong>Dynamically-sized arrays</strong>: If the next declared variable is a dynamically-sized array, the size of the array is stored at <em>0x…4</em> and then the index zero element of that array is stored at the hash of that slot, i.e. <em>keccak256(0x…4)</em>.The index k element of that array is stored at <em>keccak256(0x…4) + (k * elementSize)</em>.</li><li><strong>Mappings</strong>: If the next declared variable is a mapping, it is assigned to <em>0x…5</em>, but the storage slot is left empty. Instead, for a key <em>x</em> defined in the mapping, its value is stored at slot <em>keccak256(x,0x…5)</em>. Note that this means that one cannot iterate over mappings in contract storage without knowing all of the keys that exist in the mapping. For example, you can’t determine all of an ERC20’s token holders by looking at the balances (<em>mapping(address, uint256)</em>) in the contract storage because you need to know the token holder’s address to find their balance.</li><li><strong>Combinations of types</strong>: Where types are nested within each other recursively, the location of a value is found by recursively applying the structures above.</li></ul><p>We recommend <a href="https://programtheblockchain.com/posts/2018/03/09/understanding-ethereum-smart-contract-storage/"><em>Understanding Ethereum Smart Contract Storage</em></a> by Steve Marx; <a href="https://medium.com/coinmonks/decoding-the-memory-of-an-ethereum-contract-52c256f83f07"><em>Decoding the Storage of an Ethereum Contract</em></a><em> </em>by Inuka Gunawardana; and <a href="https://ethdebug.github.io/solidity-data-representation/"><em>Data Representation in Solidity</em></a><em> </em>by Harry Altman.</p><h4>If it just happened, it might not have happened</h4><p>Forks and reorgs mean that recent blocks that appear to be part of a consensus at a given point in time may end up being discarded, potentially along with some of the transactions and updates to state therein. Figure 4 shows a fork in which two competing valid blocks emerge (<em>Block n: A</em> and <em>Block n: B</em>), only to be resolved when an additional block emerges on one of the two chains. In this case, transactions in <em>Block n: A</em> that weren’t also included in <em>Block n: B</em> would end up being dropped even after some nodes who viewed <em>Block n: A</em> as the consensus may have represented the transaction to the user as successful.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/820/1*TZ34CILV6Y1cZbNuztIHZw.png" /><figcaption>Figure 4: A quickly resolved fork in a Proof of Work chain</figcaption></figure><p>Forks and reorgs come in varying degrees of severity. A Proof of Work consensus process may run into predictable ambiguity where 2+ valid competing blocks propagate simultaneously across the network. These may persist several blocks, but will resolve without intervention as one chain grows larger than the other. Sometimes longer forks can emerge if connectivity in the network is degraded.</p><p>Consensus can fail altogether where nodes in a network may be running different clients or different versions of the same client. While they should all be following the same consensus rules, a failure in consensus can occur if one client, or a version of a client, deviates. One example of this was a<a href="https://www.coindesk.com/tech/2020/11/11/ethereums-unannounced-hard-fork-was-trying-to-prevent-the-very-disruption-it-caused/"> hard fork created by a geth update in late 2020</a>.</p><p>There are also intentional hard forks, often to update consensus protocols. Ethereum.org maintains <a href="https://ethereum.org/en/history/">a history of these</a>. A particularly controversial example came from the first Ethereum DAO launching in 2016, <a href="https://www.coindesk.com/tech/2020/09/17/the-55m-hack-that-almost-brought-ethereum-down/">only for an assailant to discover vulnerabilities in its smart contract and siphon off $55M</a>. The Ethereum community was split on how to respond: They could simply roll back the state of Ethereum to where it was before the abuse occurred, thereby making victims whole and depriving the assailant of their gains. Many did take this approach, but others felt that such coordinated actions against the stated consensus protocol violated the decentralization at the core of Ethereum’s philosophy. Thus emerged a hard fork, which persists to this day, between the community that reverted and those that refused to revert, where the chain resulting from the latter is referred to as Ethereum Classic.</p><p>Ethereum’s move from Proof of Work to Proof of Stake substantially reduced the frequency and size of reorgs. Before the merge, one of our nodes running on the edge tended to experience reorgs about once per hour, on average. Most included just a single block, but there were longer reorgs with some frequency. The percentage of blocks in the consensus chain that explicitly reference reorged blocks is called the ommer/uncle rate: it ran <a href="https://ycharts.com/indicators/ethereum_uncle_rate#:~:text=Ethereum%20Uncle%20Rate%20is%20at,long%20term%20average%20of%208.31%25.">a little over 5% pre-merge</a>. Post-merge that rate is zero mechanically as blocks don’t reference ommers. In the few post-merge months that we’ve been running a node on the edge, we’ve experienced roughly two reorgs daily. Each of the post-merge reorgs we’ve witnessed has involved a single block. We recommend <a href="https://www.samlewis.me/2022/03/beacon-chain-reorgs/"><em>Investigating why reorgs happen in proof of stake Ethereum</em></a> by Sam Lewis for more on this.</p><h3>Conclusion</h3><p>Ethereum is a public computer with state that results from the collective action of its users. While every user with access to a node theoretically has access to that state, in practice there are many challenges to consuming that data.</p><p><em>Thank you to </em><a href="https://twitter.com/yoavw?lang=en"><em>Yoav Weiss</em></a><em>, </em><a href="https://twitter.com/moodlezoup"><em>Michael Zhu</em></a><em>, </em><a href="https://twitter.com/danboneh"><em>Dan Boneh</em></a><em>, and the smlXL team members who offered advice and feedback for this post.</em></p><p><em>Respond to this post if you have any questions.</em></p><p><em>We’re </em><a href="https://jobs.ashbyhq.com/smlxl"><em>hiring</em></a><em>!</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t3l8e1wgXLFiM6Z3puc6zA.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3ee85263134b" width="1" height="1" alt=""><hr><p><a href="https://blog.smlxl.io/how-does-ethereum-manage-data-3ee85263134b">How Does Ethereum Manage Data?</a> was originally published in <a href="https://blog.smlxl.io/">smlXL</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>