<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Bytecode Tuesday</title>
        <link>https://paragraph.com/@bytecodetuesday</link>
        <description>undefined</description>
        <lastBuildDate>Tue, 14 Apr 2026 11:26:04 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[What is Ethereum Dynamic and Static Gas?]]></title>
            <link>https://paragraph.com/@bytecodetuesday/10-what-is-ethereum-dynamic-and-static-gas</link>
            <guid>w0JbcZTSw6yDBqYfIouH</guid>
            <pubDate>Tue, 01 Jul 2025 22:39:46 GMT</pubDate>
            <description><![CDATA[This week, we answer a more fundamental question: How much does it cost to run bytecode?What Is Gas in the EVM?Every opcode in Ethereum bytecode has a gas cost, which is the fee you pay to execute that instruction. Gas prevents infinite loops and ensures that every transaction ha...]]></description>
            <content:encoded><![CDATA[<p style="text-align: center"><em>We reject abstraction<br>We believe in bytecode<br>Bytecode is only true form<br>Let’s code with bytes now</em></p><p>Last week on Bytecode Tuesday, we talked about making CALLs, how contracts can execute functions from other  contracts. This week, we answer a more fundamental question: <em>How much does it cost to run bytecode?</em></p><h2 id="h-what-is-gas-in-the-evm" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">What Is Gas in the EVM?</h2><p>Every opcode in Ethereum bytecode has a gas cost, which is the fee you pay to execute that instruction.</p><p>Gas prevents infinite loops and ensures that every transaction has a computational cost. It's Ethereum's way of making sure the network doesn’t get overloaded with spam or heavy computations. Additionally, it keeps the system healthy by rewarding validators and even removing excess ETH tokens from the system</p><p>When you send a transaction, you set a <em>gas limit</em>, which is the maximum you're willing to spend, and pay the gas used in ETH. If your transaction runs out of gas halfway through, the EVM <em>reverts</em> the entire transaction, this means no state changes, and the gas is still consumed.</p><p>However gas is not measured in ETH,  it’s just a unit. The actual ETH cost of gas is based on network demand based on the following formula:</p><pre data-type="codeBlock" text="Total Cost (in ETH) = Gas Used × Gas Price"><code><span class="hljs-function">Total <span class="hljs-title">Cost</span> <span class="hljs-params">(in ETH)</span> </span>= Gas Used × Gas Price</code></pre><h2 id="h-eip-1559-base-fee-priority-fee-and-max-fee-explained" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">EIP-1559: Base Fee, Priority Fee, and Max Fee Explained</h2><p>With the London hard fork, Ethereum introduced EIP-1559, a major change to how transaction fees are calculated. Instead of a single gasPrice, each transaction now includes:</p><ul><li><p><em>maxFeePerGas</em>: the total you're willing to pay per unit of gas</p></li><li><p><em>maxPriorityFeePerGas</em>: the tip you're offering to the validator</p></li><li><p>The network defines a <em>baseFeePerGas</em>, which must be paid and is burned, this means it is removed from circulation</p></li></ul><p>The Gas Price you actually pay is:</p><pre data-type="codeBlock" text="Gas Price = baseFeePerGas + min(priorityFee, maxFeePerGas - baseFeePerGas)"><code>Gas Price <span class="hljs-operator">=</span> baseFeePerGas <span class="hljs-operator">+</span> min(priorityFee, maxFeePerGas <span class="hljs-operator">-</span> baseFeePerGas)</code></pre><p>If <em>maxFeePerGas</em> is less than the current base fee, your transaction is invalid and won’t be included.</p><p>This means that EIP-1559 made improved user UX by making the gas costs more predictable, less competitive and even burns a part of the costs to keep ETH price more sustainable.</p><h2 id="h-gas-cost-per-opcode" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">Gas Cost per Opcode</h2><p>Each opcode has a fixed cost also called static cost, and some have extra costs called dynamic cost. Dynamic costs are based on what they do.</p><p>Let’s see some examples:<br></p><table style="min-width: 75px"><colgroup><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p>Opcode</p></td><td colspan="1" rowspan="1"><p>Static Gas Cost</p></td><td colspan="1" rowspan="1"><p>Dynamic Gas Cost Explanation</p></td></tr><tr><td colspan="1" rowspan="1"><p>ADD</p></td><td colspan="1" rowspan="1"><p>3</p></td><td colspan="1" rowspan="1"><p>No dynamic cost</p></td></tr><tr><td colspan="1" rowspan="1"><p>MUL</p></td><td colspan="1" rowspan="1"><p>5</p></td><td colspan="1" rowspan="1"><p>No dynamic cost</p></td></tr><tr><td colspan="1" rowspan="1"><p>EXP</p></td><td colspan="1" rowspan="1"><p>10</p></td><td colspan="1" rowspan="1"><p>50 * exponent_byte_size</p></td></tr></tbody></table><h2 id="h-how-dynamic-gas-costs-affect-your-contracts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">How Dynamic Gas Costs Affect Your Contracts</h2><p>When writing a contract is important to understand how gas fees affect the design of your code. The following are the tree most important gas behaviors to keep in mind. </p><p><em>Storage Writes (SSTORE) Are Expensive and Refundable:</em><br>Writing to storage costs a lot because it changes the blockchain state permanently. However, if you set a storage slot back to zero (clearing it), you get a partial gas refund. This incentivizes cleaning up state to keep the blockchain size manageable.</p><p><em>Memory Expansion Grows Quadraticall:</em><br>When your contract uses memory beyond what was used before, the gas cost increases not just linearly but quadratically. This means doubling your memory roughly quadruples the gas cost. Avoid scattered memory writes and reuse low memory offsets when possible.</p><p><em>Calls Are Costly and Variable:</em><br>Calling another contract is not just one opcode cost and since the called contract runs its own bytecode, it might consume even more gas than expected.</p><p>This article concludes our 10 week experiment on writing bytecode articles. We hope now you understand better what happens behind the scene when you code or use a smart contract.</p><p>Thanks for reading!</p>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/a676642e693dacf87ff4c5866a93f1b8.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[This is how smart contracts call each other under the hood]]></title>
            <link>https://paragraph.com/@bytecodetuesday/9-this-is-how-smart-contracts-call-each-other-under-the-hood</link>
            <guid>DeY4Rn3M0MFm879ezTMv</guid>
            <pubDate>Tue, 24 Jun 2025 18:27:30 GMT</pubDate>
            <description><![CDATA[This week, we take on one of the most powerful opcodes in the EVM toolbox: CALL.What is CALL?CALL lets your smart contract talk to other contracts (or even itself) on the ...]]></description>
            <content:encoded><![CDATA[<p style="text-align: center"><em>We reject abstraction<br>We believe in bytecode<br>Bytecode is only true form<br>Let’s code with bytes now</em></p><p>Welcome back to Bytecode Tuesday, where we pull back the curtain on what your smart contract is really doing under the hood. Last week, we looked at functions, how they're organized in bytecode and how the EVM routes execution. This week, we take on one of the most powerful opcodes in the EVM toolbox: <code>CALL</code>.</p><h2 id="h-what-is-call" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">What is CALL?</h2><p>CALL lets your smart contract talk to other contracts (or even itself) on the Ethereum blockchain.</p><p>Do you want to interact with an ERC20 token? Or invoke another contract’s function? Or even delegate work across contracts? You can do that with the <code>CALL</code> opcode.</p><p>But <code>CALL</code> isn’t just one thing, it’s a low-level instruction with a lot of parameters. Think of it like dialing a phone number where you also have to specify how much credit you’re willing to spend, what data to send, and where to store the response.</p><h2 id="h-anatomy-of-a-call" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">Anatomy of a CALL</h2><p><code>CALL</code>'s bytecode is <code>F1</code> but before the EVM can run it, you need to set up the stack with 7 arguments, in this exact order (from top to bottom of the stack):<br></p><table style="min-width: 50px"><colgroup><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Stack Position (top to bottom)</strong></p></td><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Meaning</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p>1</p></td><td colspan="1" rowspan="1"><p><code>gas</code> Amount of gas to forward</p></td></tr><tr><td colspan="1" rowspan="1"><p>2</p></td><td colspan="1" rowspan="1"><p><code>to</code> Address to call</p></td></tr><tr><td colspan="1" rowspan="1"><p>3</p></td><td colspan="1" rowspan="1"><p><code>value</code> ETH to send (in wei)</p></td></tr><tr><td colspan="1" rowspan="1"><p>4</p></td><td colspan="1" rowspan="1"><p><code>argsOffset</code> Where input starts in memory</p></td></tr><tr><td colspan="1" rowspan="1"><p>5</p></td><td colspan="1" rowspan="1"><p><code>argsLength</code> Length of input data</p></td></tr><tr><td colspan="1" rowspan="1"><p>6</p></td><td colspan="1" rowspan="1"><p><code>retOffset</code> Where to store return data</p></td></tr><tr><td colspan="1" rowspan="1"><p>7</p></td><td colspan="1" rowspan="1"><p><code>retLength</code> Max return size</p></td></tr></tbody></table><br><p>Once you push all that onto the stack, CALL consumes it and tries to make the call. If it succeeds, it pushes 1 onto the stack. If it fails, it pushes 0.</p><h2 id="h-what-happens-in-a-call" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">What Happens in a CALL?</h2><p>When one contract uses the CALL opcode to invoke another, two key pieces of data flow across:</p><ol><li><p>Input data (calldata): What we send to the other contract (e.g. function selector + parameters).</p></li><li><p>Return data: What we get back from the other contract (if any).</p></li></ol><h2 id="h-lets-see-an-example" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">Let’s See an Example</h2><p>Let’s say we want to call another contract with no ETH, send 4 bytes of data (a function selector), and expect 32 bytes back.</p><p>Here’s the bytecode to make that happen:</p><pre data-type="codeBlock" text="PUSH1 0x20				// return data length = 32
PUSH0						// return data offset = 0
PUSH1 0x04				// call data length = 4
PUSH0						// call data offset = 0
PUSH0						// value to send = 0
PUSH20 &lt;address&gt;	// the contract address
PUSH2 0xFFFF			// gas = 65535 (for example)
CALL"><code>PUSH1 <span class="hljs-number">0x20</span>				<span class="hljs-comment">// return data length = 32</span>
PUSH0						<span class="hljs-comment">// return data offset = 0</span>
PUSH1 <span class="hljs-number">0x04</span>				<span class="hljs-comment">// call data length = 4</span>
PUSH0						<span class="hljs-comment">// call data offset = 0</span>
PUSH0						<span class="hljs-comment">// value to send = 0</span>
PUSH20 <span class="hljs-operator">&lt;</span><span class="hljs-keyword">address</span><span class="hljs-operator">&gt;</span>	<span class="hljs-comment">// the contract address</span>
PUSH2 <span class="hljs-number">0xFFFF</span>			<span class="hljs-comment">// gas = 65535 (for example)</span>
CALL</code></pre><p>We assume the calldata (like a function selector) is already stored in memory at offset <code>0x00</code>.</p><p>And the actual bytecode form would be: <code>60205F60045F5F73&lt;address&gt;61FFFFF1</code>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b591a2fc1ccec76af007f45e8a847cf0.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAACOElEQVR4nM2Uz4vaQBTHw6IiyOqyXaom0ZomEWNqEv0341FPav8Je7CNBw+RQg+yR/EkuP5oXJOB+CsTs1PMuNuwC6UFhX545H3zmJdv3sAMcTgc4DOu6zqO47ru0/kg1uv1w8N0Op3OZjPTNCeTiWEsEUJnM3jy8TwvUAzqMxlcDuJ/MfB8LmiAfC5igBCybXs8Hs9mM9d10b/wtwa73d40TQAAPisYCOH+j+DzRLza5Vcb7XkeQmg0Gv3w6Xa7mqZ1Ol817Vuv17u/H+h63zAMy7LMAJZlLRY/5/MFQuhk8Ha0oMFwOOz3v+u6/sWn3W53Oh1N0waDga7ry+USAGAFAAAYxvJkACE8HA6mac3ni8fl42K+sCwreH9ACA3DAABst9v9fr/b7fBzu91uNhv8+1gHWa/Xtm1DCI8TIIRWq5XjOAghCKFpmngIdA6IZrPR/Nys1+uqqlarVVVVa7Vaq9VqnoNGo0HEb2KJd7HEXSx+G7t9H0/cXd8kryPRSCgUCofDVydCfgTF1Vvx0oJFOByORiMESZE55oNSLglCnudZWSl+kgqFQr5Q4Hmeq1QkRSnKsiBJxXJZkiVRlkVZLilKSRQFRSmVyyVJKsqyWKnIgpDP5zlJEkVR4HmWYRiSJIlUMpVOpVn2YzaboWmSYXLZbCaboTM0TdMUxzEsm8PBsQHN/S7iOscxuJdhcn4vTVFkMpkksEynSZIkKYo6Jl9g8OsLx1VpnJ4r6WNggVuDH6Bp+hc/Sx5kI4NWhAAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Step by step animation of making a contract call to the <code>helloWorld()</code> function (selector <code>0xC605F76C</code>) at contract  <code>0xBA5EBA11BA5EBA11BA5EBA11BA5EBA11BA5EBA11</code></figcaption></figure><p>After the <code>CALL</code>, the result (success or failure) will be on the top of the stack.</p><h2 id="h-error-handling-with-call" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">Error Handling with CALL</h2><p>Unlike Solidity, which reverts on failed external calls by default, raw <code>CALL</code> does not. If the call fails, you just get 0 on the stack and it’s up to you to decide what to do.</p><p>So if you want to revert on error, you must explicitly check.</p><h2 id="h-other-call-opcodes" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0">Other CALL Opcodes</h2><p>Here’s a quick table of the family of call-related opcodes:<br></p><table style="min-width: 75px"><colgroup><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Opcode</strong></p></td><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Name</strong></p></td><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Description</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p><code>F1</code></p></td><td colspan="1" rowspan="1"><p><code>CALL</code></p></td><td colspan="1" rowspan="1"><p>Call another contract</p></td></tr><tr><td colspan="1" rowspan="1"><p><code>F2</code></p></td><td colspan="1" rowspan="1"><p><code>CALLCODE</code></p></td><td colspan="1" rowspan="1"><p>Legacy version, now discouraged</p></td></tr><tr><td colspan="1" rowspan="1"><p><code>F4</code></p></td><td colspan="1" rowspan="1"><p><code>DELEGATECALL</code></p></td><td colspan="1" rowspan="1"><p>Runs code in the context of the caller</p></td></tr><tr><td colspan="1" rowspan="1"><p><code>FA</code></p></td><td colspan="1" rowspan="1"><p><code>STATICCALL</code></p></td><td colspan="1" rowspan="1"><p>Like CALL but disallows state modification</p></td></tr></tbody></table><br><p>The <code>CALL</code> opcode is low-level and flexible. It exposes everything gas, calldata, return handling, and value transfers. While Solidity wraps it in nice syntax, EVM developers get to shape the whole interaction exactly how they want.</p><p>See you next Tuesday for our last Bytecode Tuesday release!</p>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/6e5bf6fbe88ad96c66ad889028671afe.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[How smart contract functions *really* work]]></title>
            <link>https://paragraph.com/@bytecodetuesday/8-how-smart-contract-functions-really-work</link>
            <guid>051ZnKsDclw7YIERavmK</guid>
            <pubDate>Tue, 17 Jun 2025 19:24:18 GMT</pubDate>
            <description><![CDATA[On this week we're going to implement functions that can be called by any ethereum account or smart contract. Is important to understand how function call work under the hood to be able to write better and safer smart contract, optimize, and integrate with any tooling available today. Additionally, this way we can prepare for future updates where EVM get's improved. We are...]]></description>
            <content:encoded><![CDATA[<p>Welcome back to Bytecode Tuesday, in previous articles we created smart contracts with different logic applied into them. On this week we're going to implement functions that can be called by any ethereum account or smart contract.</p><p>Is important to understand how function call work under the hood to be able to write better and safer smart contract, optimize, and integrate with any tooling available today. Additionally, this way we can prepare for future updates where EVM get's improved.</p><p>We are going to create a smart contract that has two functions as shown in the following pseudocode:</p><pre data-type="codeBlock" text="MyContract {
  a() {
    return 4
  }
  b() {
    return 5
  }
}"><code><span class="hljs-title class_">MyContract</span> {
  <span class="hljs-title function_">a</span>(<span class="hljs-params"></span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-number">4</span>
  }
  <span class="hljs-title function_">b</span>(<span class="hljs-params"></span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-number">5</span>
  }
}</code></pre><p>But before writing it we need to understand a concept introduced into the Ethereum ecosystem very early on: <em>Function Signature Hashing</em>.</p><h2 id="h-what-are-functions-signatures" class="text-3xl font-header">What are functions signatures?</h2><p>Function signatures are a standard and particular way to express the function names and parameters, for example the following is the ERC20 function signatures. Notice no spaces, also the return values are not expressed.</p><pre data-type="codeBlock" text="name()
symbol()
decimals()
totalSupply()
balanceOf(address)
transfer(address,uint256)
transferFrom(address,address,uint256)
approve(address,uint256)
allowance(address,address)"><code><span class="hljs-built_in">name</span>()
<span class="hljs-built_in">symbol</span>()
<span class="hljs-built_in">decimals</span>()
<span class="hljs-built_in">totalSupply</span>()
<span class="hljs-built_in">balanceOf</span>(address)
<span class="hljs-built_in">transfer</span>(address,uint256)
<span class="hljs-built_in">transferFrom</span>(address,address,uint256)
<span class="hljs-built_in">approve</span>(address,uint256)
<span class="hljs-built_in">allowance</span>(address,address)</code></pre><p>However , just as any bytecode language, the EVM has no native string implementation, it only has bytes. So in order to express function names in bytecode, the early ethereum community decided to hash the function names and grab the first 4 bytes. Those 4 bytes will represent the function names inside of EVM bytecode contracts. The following are ERC20 function signatures.</p><ul><li><p>name(): <code>0x06fdde03</code></p></li><li><p>symbol(): <code>0x95d89b41</code></p></li><li><p>decimals(): <code>0x313ce567</code></p></li><li><p>totalSupply(): <code>0x18160ddd</code></p></li><li><p>balanceOf(address): <code>0x70a08231</code></p></li><li><p>transfer(address,uint256): <code>0xa9059cbb</code></p></li><li><p>transferFrom(address,address,uint256): <code>0x23b872dd</code></p></li><li><p>approve(address,uint256): <code>0x095ea7b3</code></p></li><li><p>allowance(address,address): <code>0xdd62ed3e</code></p></li></ul><p>This standard has been adopted by high level languages (solidity, vyper), indexers (etherscan, blockscout) and JS tooling (ethers, viem). It has been rightfully criticized of being too gas expensive, it can express more than 4 billion functions per contract where 1 byte can serve 256 functions, more than enough for most, if not all, contracts deployed on ethereum. That being said, this format has served to build a lot of tooling a provide good developer experience because it has been widely adopted across the all EVM usage.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/24dbb3d09fa368a5101f0c3c31880b1e.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAIAAAAUMWhjAAAACXBIWXMAAAsTAAALEwEAmpwYAAADfklEQVR4nKVWW2gTWRg+Pi77pPviw7747pNgXF98UBBWEFzK+lC80F1YFlxYFPFCoeiq3bRJE6zZ7bqpiTSxiUltsFaxlqBxmyZNt9OZNt7abS5mmmkmnUsyyYknM3Gkc2KxZdE6+fgY/vmZ4eP/zv+fcwBaQfUNqkJYqSBUQQjCCo5XM0iLEaqu4/8m1xFAWFE3BlmW4RskK7VVvt3AX0CSSqqqhqMxu9Pd7w8UpVLon3H7jT63987NW7f7/QGHyxufmTF6H4Ivd4Cv94Atu8BX34AtBgC2g30/qKr6cRlQ1ARu3vLtO/BdU3MLk2MdfR7Dnv1NzS1NzS37D36/e++3A17frlMmsIKtAGwC4AsANmvBtk9XUIZQVdUKQrIsI1TFT0VRcIC05UEILeaFHy2uw1fsx03OI0bHcZOz6be/bj+e/HQF2CI+QydISiwW2RXkOY5Lp18zzBLU5BsBEMWCqqpDxq5zew/cGRnptfe6XO7h4eGuLovFap2f/w9/91ZVkSyvoyzLG7VIUWqKBlzvikVVWdGy+FU36gI5Nr+QSJIz8SmCir+Ym37+MjxFxshZ8vmrsRhBZ5lljtfH+hq8nJv3+AOnzrUZzd29Dtfpn385dujwrz+dMF3pOHPyLEmSRamUY/N6BHAFklQSxYIkSahWW4jEDAAYANip0QBAz5GjZUVZZlleED6XdQFRLGSZpRybp7NMMpGM3n/42OsbuW4fsdkeddtS8bhYghzH84L4uawPGjUTd7o8nZZrVtv11gvt5y93tLabz1wyhgkKKkqeF/SvAa5gmeOzzFIqncnQ2XSGXkgkM/RiMvWaphdZNs/qcn+NAN41FUXRts56UEGoDGGhWGyEdYviL+bc3oEL7aY//nYazd1tF9s7rbbfO62+wXs5lmuE9QqyzBJBzY6NT4yNR2OTxNj4xNNwJPYvSZCzus1ZYxE+PbThlxVto8ezDWFFR+es6SI8aAuJ1Ggw5PEHPP6A0+XBtHT3RCentBHjGp3kufkEFhi8e7+v3+f2DvgGhxx9nsjEFC+ITI7NsXl9/NAiiE+C96jhfKHBLsIVpNIZKv4sEp0kpqmn4choMPQo+GQ0GBoNhjL0Ii80MGi4TYlpKjD0wHz1z16n22i+erb14uUO67Ue+/m2S8Q0xQuCbpfqFpUhlKSSdj2BZe02sjpoDXbRO7bB5UGVrHK+AAAAAElFTkSuQmCC" nextheight="675" nextwidth="899" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">You can see function signatures displayed on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/token/0x6b175474e89094c44da98b954eedeac495271d0f#writeContract">Etherscan</a></figcaption></figure><h2 id="h-how-to-pass-data-to-functions" class="text-3xl font-header">How to pass data to functions</h2><p>The standard in which any Ethereum account and smart contract can call functions on another smart contract is by sending data to another smart contract in the following format:</p><pre data-type="codeBlock" text="<4 byte signature><32 byte Param1><32 byte Param2><32 byte Param3>..."><code><span class="hljs-operator">&lt;</span><span class="hljs-number">4</span> <span class="hljs-keyword">byte</span> signature<span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-number">32</span> <span class="hljs-keyword">byte</span> Param1<span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-number">32</span> <span class="hljs-keyword">byte</span> Param2<span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-number">32</span> <span class="hljs-keyword">byte</span> Param3<span class="hljs-operator">&gt;</span>...</code></pre><p>Data received can be read by calling the opcode <code>CALLDATALOAD</code> (aka 0x35) that receives a byte offset to be read.</p><h2 id="h-now-lets-go-back-to-our-example" class="text-3xl font-header">Now let's go back to our example</h2><p>We now know everything we need to create the contract we will be showcasing step-by-step.</p><pre data-type="codeBlock" text="MyContract {
  a() {
    return 4
  }
  b() {
    return 5
  }
}"><code><span class="hljs-title class_">MyContract</span> {
  <span class="hljs-title function_">a</span>(<span class="hljs-params"></span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-number">4</span>
  }
  <span class="hljs-title function_">b</span>(<span class="hljs-params"></span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-number">5</span>
  }
}</code></pre><p>The pseudocode smart contract entry (function dispatcher):</p><pre data-type="codeBlock" text="signature = CALLDATALOAD(0) // read first 4 bytes of call data
if signature == 0x0DBE671F			// this is the a() function signature
	goto a();
else
	goto b();"><code>signature = CALLDATALOAD(<span class="hljs-number">0</span>) <span class="hljs-comment">// read first 4 bytes of call data</span>
<span class="hljs-keyword">if</span> signature == <span class="hljs-number">0x0DBE671F</span>			<span class="hljs-comment">// this is the a() function signature</span>
	<span class="hljs-function"><span class="hljs-keyword">goto</span> <span class="hljs-title">a</span>()</span>;
<span class="hljs-keyword">else</span>
	<span class="hljs-function"><span class="hljs-keyword">goto</span> <span class="hljs-title">b</span>()</span>;</code></pre><p>Notice that we are not using params and we assume that, if a() was not called b() will be called. This is not normally the case in smart contracts but understanding this simple example will give you solid foundations to understand more complex contracts later on.</p><p>The following is the smart contract runtime bytecode implementation:</p><pre data-type="codeBlock" text="5F		// PUSH0, which is a more gas efficient way of performing PUSH1(0)
35		// CALLDATALOAD
7F 0DBE671F00000000000000000000000000000000000000000000000000000000	// PUSH the a() function signature
14		// EQ, if the top 2 elements stacks are equal they get replaced by 0x01, otherwise by 0x00
60 2F	// PUSH1(0x2F) this is the function a() code destination, at byte 47
57		// JUMPI Jumps to byte 47 (0x2F) if the top of the stack is 0x01
// This is now function b() code
60 05	// PUSH1(0x05) the b() return value is now on the stack
5F		// PUSH0 we will place it on the memory to return it
52		// MSTORE 0x05 is not on memory
60 20	// PUSH1(0x20) Return size is 32 bytes, 0x20
5F		// PUSH0 pushes the offset of memory returned
F3		// RETURN
// This is function a() code, very similar to b()
5B		// JUMPDEST signals a safe landing for JUMPI 
60 04	// PUSH(0x04) Pushes the a() return value
5F		// PUSH0 Memory location where the number 0x04 will be placed
52		// MSTORE The return value is now on memory
60 20	// PUSH1(0x20) Return value is 32 bytes, 0x20
5F		// PUSH0 The location of the value returned, in memory
F3		// RETURN
"><code><span class="hljs-number">5</span><span class="hljs-selector-tag">F</span>		<span class="hljs-comment">// PUSH0, which is a more gas efficient way of performing PUSH1(0)</span>
<span class="hljs-number">35</span>		<span class="hljs-comment">// CALLDATALOAD</span>
<span class="hljs-number">7</span><span class="hljs-selector-tag">F</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">DBE671F00000000000000000000000000000000000000000000000000000000</span>	<span class="hljs-comment">// PUSH the a() function signature</span>
<span class="hljs-number">14</span>		<span class="hljs-comment">// EQ, if the top 2 elements stacks are equal they get replaced by 0x01, otherwise by 0x00</span>
<span class="hljs-number">60</span> <span class="hljs-number">2</span><span class="hljs-selector-tag">F</span>	<span class="hljs-comment">// PUSH1(0x2F) this is the function a() code destination, at byte 47</span>
<span class="hljs-number">57</span>		<span class="hljs-comment">// JUMPI Jumps to byte 47 (0x2F) if the top of the stack is 0x01</span>
<span class="hljs-comment">// This is now function b() code</span>
<span class="hljs-number">60</span> <span class="hljs-number">05</span>	<span class="hljs-comment">// PUSH1(0x05) the b() return value is now on the stack</span>
<span class="hljs-number">5</span><span class="hljs-selector-tag">F</span>		<span class="hljs-comment">// PUSH0 we will place it on the memory to return it</span>
<span class="hljs-number">52</span>		<span class="hljs-comment">// MSTORE 0x05 is not on memory</span>
<span class="hljs-number">60</span> <span class="hljs-number">20</span>	<span class="hljs-comment">// PUSH1(0x20) Return size is 32 bytes, 0x20</span>
<span class="hljs-number">5</span><span class="hljs-selector-tag">F</span>		<span class="hljs-comment">// PUSH0 pushes the offset of memory returned</span>
<span class="hljs-selector-tag">F3</span>		<span class="hljs-comment">// RETURN</span>
<span class="hljs-comment">// This is function a() code, very similar to b()</span>
<span class="hljs-number">5</span><span class="hljs-selector-tag">B</span>		<span class="hljs-comment">// JUMPDEST signals a safe landing for JUMPI </span>
<span class="hljs-number">60</span> <span class="hljs-number">04</span>	<span class="hljs-comment">// PUSH(0x04) Pushes the a() return value</span>
<span class="hljs-number">5</span><span class="hljs-selector-tag">F</span>		<span class="hljs-comment">// PUSH0 Memory location where the number 0x04 will be placed</span>
<span class="hljs-number">52</span>		<span class="hljs-comment">// MSTORE The return value is now on memory</span>
<span class="hljs-number">60</span> <span class="hljs-number">20</span>	<span class="hljs-comment">// PUSH1(0x20) Return value is 32 bytes, 0x20</span>
<span class="hljs-number">5</span><span class="hljs-selector-tag">F</span>		<span class="hljs-comment">// PUSH0 The location of the value returned, in memory</span>
<span class="hljs-selector-tag">F3</span>		<span class="hljs-comment">// RETURN</span>
</code></pre><p>And the following is the full string of bytes.</p><p><code>5F357F0DBE671F0000000000000000000000000000000000000000000000000000000014602F5760055F5260205FF35B60045F5260205FF3</code></p><p>But it's easier to understand with the following animation.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/957da4ea5fb994ea32ace416a32ef020.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAACJElEQVR4nLWUXW/aMBSGrQom2krttO2G2M5CIB8NFbCL7c+yv9Vdskr5IAsoQaFJSGLiCRtS08EUNO1RZL3H5xy/thIHEELyPC+KQhjLqqq2jIpBCCmKYrPZFIwkSbIsy/O8EqiL32iwXq8dx3Fd1/O8MAxt2w6CgFJaV1BK0zR1XXc2mwVBsFwun55+cC0udA7wp+dJtoeCJoueMLiILfNo6AT+cYM14js7egdVAwghYv85TtaAhlumjHOr/MUGiP01b5aO4/j5+afneWVZ0kt4NSjLciNACKm3QynNsiwMwyiK0jTbNKYsd/cJUEoJIY7jhIwoivjHTinlh6WUep4XBEEcx2EzoijyfX8+n1NK9wa2bYsGi8VCNHBd1/f91WrFC6IoEsUpg5Xv/9ob8NufpumLQP1X4PDtJ0lyyHNRhydYM4qi2J3gvwKm0+n3S5ge6gVRp151PQOu7zt3H2/uP9127jo37zu3H5i+7lxdtVrt9m5stUWxG1ss5JqNLMsKjrPt9jvQ11TT1HR9MHw0v36bTL5YjyOr11MMQzOMwWhkGqamaep4PLQs3TQ1w9BMUxuPH3R9YBzCycSyhgZr4dmhrg/MB13tqwBCCWOEEMIYaZqqqoqiYEmSZBkjBFW1hzGCUGLznzFGsoxlGff7CsIIYyjLCMu4pyqyjI+yCPJGACGU+CPBbrcrMXaTEpvZR5BlDpUshDxkZUddPMs0hOg3h+kio3pPd1EAAAAASUVORK5CYII=" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Step by step animation of a simple function call in EVM bytecode</figcaption></figure><p>We hope you now have more clarity on how EVM smart contract functions work, this knowledge is fundamental for security auditors, builders and users to have the best results out the EVM and to prepare for future upgrades.</p><p>Thanks for reading, see you next Tuesday for more bytes!</p><br>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <category>ethereum</category>
            <category>evm</category>
            <category>solidity</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/7916fe3078cf85f4b7e41bd0b4a435cc.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Intro to Transient Storage at Bytecode Level]]></title>
            <link>https://paragraph.com/@bytecodetuesday/7-transient-storage</link>
            <guid>ZhWM4lPi6jWcS56sswSy</guid>
            <pubDate>Tue, 10 Jun 2025 16:12:42 GMT</pubDate>
            <description><![CDATA[This week, we're diving into a recent (Dencun update) and powerful EVM feature: Transient Storage.Why Do We Need Transient Storage?We already know the three main data regions in the EVM: the stack witch is super fast but only lasts for the current instruction, the memory that resets after each all a...]]></description>
            <content:encoded><![CDATA[<p style="text-align: center"><em>We reject abstraction<br>We believe in bytecode<br>Bytecode is only true form<br>Let’s code with bytes now</em></p><p>Last week, we dissected smart contract deployment and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://paragraph.com/@bytecodetuesday/6-smart-contract-structure">how to separate init code from runtime code</a>.</p><p>This week, we're diving into a recent (Dencun update) and powerful EVM feature: Transient Storage.</p><h2 id="h-why-do-we-need-transient-storage" class="text-3xl font-header">Why Do We Need Transient Storage?</h2><p>We already know the three main data regions in the EVM: the stack which is super fast but only lasts for the current instruction, the memory that resets after each all and the persistent storage.</p><p>But there’s a gap:<br>What if we want to share temporary data between cross contract calls in a single transaction. Specifically in cases where data doesn’t need to persist after the transaction ends.</p><p>That’s where Transient Storage comes in.</p><h2 id="h-what-is-transient-storage" class="text-3xl font-header">What Is Transient Storage?</h2><p>Transient Storage is like ephemeral memory that survives across calls but gets wiped at the end of the transaction. It’s a key-value store like regular <code>SSTORE</code>, but it’s cheaper and isolated to the current transaction.</p><h2 id="h-the-opcodes-tstore-and-tload" class="text-3xl font-header">The Opcodes: TSTORE and TLOAD</h2><p>Ethereum introduced two new opcodes (with EIP-1153 in Decun update) to interact with transient storage:<br></p><table style="min-width: 75px"><colgroup><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p><strong>Opcode</strong></p></td><td colspan="1" rowspan="1"><p><strong>Name</strong></p></td><td colspan="1" rowspan="1"><p><strong>Description</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p>5C</p></td><td colspan="1" rowspan="1"><p><code>TLOAD</code></p></td><td colspan="1" rowspan="1"><p>Load a value from transient storage</p></td></tr><tr><td colspan="1" rowspan="1"><p>5D</p></td><td colspan="1" rowspan="1"><p><code>TSTORE</code></p></td><td colspan="1" rowspan="1"><p>Store a value into transient storage</p></td></tr></tbody></table><p><br>These behave exactly like <code>SLOAD</code> and <code>SSTORE</code>, except the data is not persistent and can be use across smart contract calls.</p><h2 id="h-example" class="text-3xl font-header">Example:</h2><p>Imagine a contract where Contract A sets a flag, calls Contract B, B calls A again, and then A checks that flag. With transient storage, Contract A can do this without writing to permanent storage.</p><p>Here’s a simplified outline:</p><pre data-type="codeBlock" text="PUSH1 0x01		// Value to write
PUSH1 0x00		// Key to write
TSTORE				// Store 1 into transient[0]

CALL					// Call logic (Abstracted because have not discussed it here yet)


// Reentry point
PUSH1 0x00		// Key to read
TLOAD				// Read from transient[0]"><code>PUSH1 <span class="hljs-number">0x01</span>		<span class="hljs-comment">// Value to write</span>
PUSH1 <span class="hljs-number">0x00</span>		<span class="hljs-comment">// Key to write</span>
TSTORE				<span class="hljs-comment">// Store 1 into transient[0]</span>

<span class="hljs-built_in">CALL</span>					<span class="hljs-comment">// Call logic (Abstracted because have not discussed it here yet)</span>


<span class="hljs-comment">// Reentry point</span>
PUSH1 <span class="hljs-number">0x00</span>		<span class="hljs-comment">// Key to read</span>
TLOAD				<span class="hljs-comment">// Read from transient[0]</span></code></pre><p>Unlike memory (which resets when there is an external call), this value remains accessible to all internal functions during the transaction.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c9637802a825bfbe960b0bff57658fc6.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAADI0lEQVR4nK2UUWubUBTHDaULMhKq1SQvY2Vru43uYWP7FrVjS7d9xr61jDEo20MohEJBoyEJUtqp02jU1KQqCTd6c4fX1tmshD3sx/FyvJ57/55zjxLz+Rxh5pi8nwfdN5nF/00WQARB0O/3zQTL8zzDMBzHyUcghHzfV1XVtu10BkKYPRqPx7quJ4sty3WHhmGoqhoEQbYDEUXR5BYAQBiGk8lk4TWjKMrm4zjOa89mszAMfd+fTCZpzGg0AgD8EViSXQaE0LIsHSPLsud5CKE0Dwih4ziG0cdmXF1dLdSTyLbIs1BlAECv1zs/PxdFSRBaiqKkAmkGiqLqut5ud1zXVVU1iqJ7BJYkgRCaToGmaa7rXmJM08wySAsIAJjNZgCAKIoWsk8EIITD4fAK43me6w7zpzTHdXcd17GdwWBgWdb19fVCFyypcHIGURQZhhEEAT6kied5aSPla4XubgH/gTsZdLtdURR5nhdFURBa+SIghMIwtKykidO6/zt3BARBODo6Ojk5abVa/X4/FYB4R9M0eZ6XJElRVE37pWmaruuqqimKenn5czAY2HdxHMeyrPF4jBC6OWSe5xuNxrev375//9FoNHRdzwvIsnx2dtbpdL5gDg8PDw4Oms1mp9NuNptBEMRxPMNEmDiOgyC0bftGAELY6/UkSTo+Pj49PW2322kGMQYhdHFx0Wq1ZFkWbxEEodvtyrIsSZLjOJ7npT2SdYpt267r3ggghEajkWmaw+HQtm3TNKfTaf7v5Ps+ACDVgxBmY/q+4D6mmPu/5P8LUd//sP+5vv+5njif6vWPye37D+/fYTiO293l9ri93V2O4/byls5zHPduKUSRXCVLxYfl4iq5SpaLZKlIrj1YWVkhiEKBKNA0VakwJElWKyxNlylqjaJK5dLDcrlUq1XK5RJFrRUKN8F5I7AlDk2vJ0atMzTzx2dYBl87O89ev97Z2Hj05s3LFy+2t7c3NzefbDx+9Pz51tu3r54+eby19ZRlk+B0Sc5h2cQYolqtVau12l8jtmqiSq1X2MqtKsuyFZatMAxLU3TiM2x1Kb8BL1QxzjA1M4AAAAAASUVORK5CYII=" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Step by step animation of <code>TSTORE</code> and <code>TLOAD</code> usage</figcaption></figure><h2 id="h-hands-on-transient-vs-persistent" class="text-3xl font-header">Hands-On: Transient vs Persistent</h2><p>Let’s store and retrieve a value both in transient and persistent storage to compare:</p><pre data-type="codeBlock" text="// Transient Store
PUSH1 0x2A
PUSH1 0x00
TSTORE
// Transient Load
PUSH1 0x00
TLOAD
// Persistent Store
PUSH1 0x2A
PUSH1 0x01
SSTORE
// Persistent Load
PUSH1 0x01
SLOAD"><code><span class="hljs-comment">// Transient Store</span>
PUSH1 <span class="hljs-number">0x2A</span>
PUSH1 <span class="hljs-number">0x00</span>
TSTORE
<span class="hljs-comment">// Transient Load</span>
PUSH1 <span class="hljs-number">0x00</span>
TLOAD
<span class="hljs-comment">// Persistent Store</span>
PUSH1 <span class="hljs-number">0x2A</span>
PUSH1 <span class="hljs-number">0x01</span>
SSTORE
<span class="hljs-comment">// Persistent Load</span>
PUSH1 <span class="hljs-number">0x01</span>
SLOAD</code></pre><p>As you can see, the call API is very similar but when the transaction ends, the persistent value at slot <code>0x01</code> remains on-chain while the transient value at slot <code>0x00</code> is gone.</p><h2 id="h-use-cases-for-transient-storage" class="text-3xl font-header">Use Cases for Transient Storage</h2><ul><li><p><strong>Re-entrancy Guards: </strong>Instead of storing a boolean in storage (expensive), store a flag in transient storage.</p></li><li><p><strong>Efficient Intermediate Values: </strong>Use transient slots to coordinate between multiple contract calls without touching global state nor calldata parameters.</p></li><li><p><strong>Gas-Efficient Caching: </strong>Cache data temporarily across contract calls in the same transaction.</p></li></ul><h2 id="h-visual-recap" class="text-3xl font-header">Visual Recap<br></h2><table style="min-width: 125px"><colgroup><col><col><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Region</strong></p></td><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Lifetime</strong></p></td><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Access Pattern</strong></p></td><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Gas Cost</strong></p></td><td colspan="1" rowspan="1"><p style="text-align: center"><strong>Shared Across Calls?</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p>Stack</p></td><td colspan="1" rowspan="1"><p>One operation</p></td><td colspan="1" rowspan="1"><p>LIFO</p></td><td colspan="1" rowspan="1"><p>Very low</p></td><td colspan="1" rowspan="1"><p><span data-name="cross_mark" class="emoji" data-type="emoji"><img src="https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/274c.png" draggable="false" loading="lazy" align="absmiddle"></span> No</p></td></tr><tr><td colspan="1" rowspan="1"><p>Memory</p></td><td colspan="1" rowspan="1"><p>One transaction (until there is a call)</p></td><td colspan="1" rowspan="1"><p>Byte offset</p></td><td colspan="1" rowspan="1"><p>Low</p></td><td colspan="1" rowspan="1"><p><span data-name="cross_mark" class="emoji" data-type="emoji"><img src="https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/274c.png" draggable="false" loading="lazy" align="absmiddle"></span> No</p></td></tr><tr><td colspan="1" rowspan="1"><p>Storage</p></td><td colspan="1" rowspan="1"><p>Forever</p></td><td colspan="1" rowspan="1"><p>Key-value</p></td><td colspan="1" rowspan="1"><p>High</p></td><td colspan="1" rowspan="1"><p><span data-name="check_mark_button" class="emoji" data-type="emoji"><img src="https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/2705.png" draggable="false" loading="lazy" align="absmiddle"></span> Yes</p></td></tr><tr><td colspan="1" rowspan="1"><p>Transient</p></td><td colspan="1" rowspan="1"><p>One transaction</p></td><td colspan="1" rowspan="1"><p>Key-value</p></td><td colspan="1" rowspan="1"><p>Low-medium</p></td><td colspan="1" rowspan="1"><p><span data-name="check_mark_button" class="emoji" data-type="emoji"><img src="https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/2705.png" draggable="false" loading="lazy" align="absmiddle"></span> Yes</p></td></tr></tbody></table><h2 id="h-try-it-yourself" class="text-3xl font-header">Try It Yourself</h2><p>Write and check using this <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://evmdisassembler-cooldev1337.pages.dev/">EVM Disassembler</a> bytecode that:</p><ol><li><p>Stores <code>0xAA</code> in transient slot <code>0x00</code></p></li><li><p>Loads it from the same slot</p></li><li><p>Returns it</p></li></ol><p>We’ve now seen how to manage state across contract calls, next Tuesday, we’ll look at how contracts organize their dispatch logic using functions. Subscribe for more bytes.</p>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <category>protocol</category>
            <category>ethereum</category>
            <category>bytecode</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/afc7e21aace78011fad18be17110c671.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Smart Contract Deployment at Bytecode Level]]></title>
            <link>https://paragraph.com/@bytecodetuesday/6-smart-contract-structure</link>
            <guid>2LenlYVenBmdjvphlFjO</guid>
            <pubDate>Tue, 03 Jun 2025 17:26:36 GMT</pubDate>
            <description><![CDATA[What happens when you deploy a contract? When you deploy a smart contract, you’re sending a special transaction where:to = 0x0 (indicating contract creation)data = <contract bytecode>But that <contract bytecode> is not ju...]]></description>
            <content:encoded><![CDATA[<p style="text-align: center"><em>We reject abstraction<br>We believe in bytecode<br>Bytecode is only true form<br>Let’s code with bytes now</em></p><p>So far, we’ve explored how the EVM reads bytecode, how it handles memory and storage, and how it controls program flow with jumps. But here’s a question we haven’t answered yet: <em>what happens when you deploy a contract?</em></p><p>When you deploy a smart contract, you’re sending a special transaction where:</p><ul><li><p>to = 0x0 (indicating contract creation)</p></li><li><p>data = &lt;contract bytecode&gt;</p></li></ul><p>But that &lt;contract bytecode&gt; is not just the logic of your contract. It’s a complete program that runs once during deployment. This program:</p><ol><li><p>Runs your constructor</p></li><li><p>Uses the <code>RETURN</code> opcode to return the runtime code to the EVM</p></li></ol><p>What the EVM stores to the blockchain is only the runtime code.</p><h2 id="h-contract-deployment-transaction-main-parts" class="text-3xl font-header">Contract Deployment Transaction Main Parts</h2><p>When you deploy a new contract, the calldata bytecode of that transaction is usually divided into two parts.</p><p><em>1. Init Code</em></p><p>This is the first part of the bytecode. It executes only once at deployment. It starts by running the constructor logic where it can do writes in the storage if needed. Then returns the actual runtime code using the <code>RETURN</code> opcode.</p><p>When <code>RETURN</code> is called in the constructor, the value returned becomes the runtime code that is stored on-chain at your contract’s address.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2879ffb30d9b8020077841c754264934.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAARCAIAAAAzPjmrAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAABDtJREFUeJxlVG1z2kYQdiZNhiG2x8HtD+6nfOuXzvQX9HNbE9tjLNDL6Y4TOt1JJ95sgzEIgSSDMI4bp66B65xIMJnuPLNaPbs3q9Xu3s7BwcHh4WGhUDh4//7d7v7evsS73f1CofDj4U/vDwq5XP7t27f5XH43t5vPvXv9+vXOq50MrzbYyA9v3uRzud18fm9vb39/P5fL7Tw9PT1+fkzTeTR7iObz6Xw+m99P7r/EaXwRNHujbj++SdIojAetvn81bI2jaBwlo3EcJ5NxlEQZRuMoGI4m0zQcx0E/mKbz29l8sVj4vr8jhFgJ8fD5IU7iOIkn08li+SyEGN+F1ZbmdHBzyK/CRrWllcifRv1s/ncqhFiK5UqsVqvVYrkUQiRpetXrdwfDMI6vh2F3MIySWyFEu92WCRaL54tuCxPLZoS4DuGU+q7jUuJSwhnhlLiOzYjjUseljLvUdyXJ5Sthjgxzac2xpc2ZzUjVqQ3CwVaC5cJr8IoKAMQGgAaAOoCqBlTN0A1TAkAAqibEqmYYmb12GQBWNENG6qCSMSaysrPGYBS8JHhePrc7FzahhDLmccpcylyb0MzwKHM9j3vcl9rjjLke9xlzmedlwYxSJg9mYczjPPOGUfhdBbTOzpTymVJWVLVUVjda0TRF1f8qVY7OlKOzynFZl1C0YkktltSTsn5UqqztYkk9VrSTslEsqX+cnneD/nYFS+i3iiooqvCjDk9VdKyjExUdlSVzoleLKjw38bmJFdNSzJpiWqcVWAJYMWtrnfGWAu1KlSimVVThZbDV5KfFyvKvwLcfvQGAaN0DwwC6ASoVHQJgWxhChKGJEVoDAqBpGgQAAYgRrOGqDtFVkLwk+HexjNP7WymTcRSPoyjKdJLcxsntMBwFwzAIRtF4jOrdc3IZhGPc6qH6tdW8Ju1+szvo9ALD6zS6A7PehfXuzXCUzD69JFitVo9fvswyeXqWS/B/WchxF2on/VDulTuzX/Sb39DwtD35FfR/p6PbT/8cNSen7emHcu/n0nV0/5Rt16aC5QrVu9kfR3qNV902ok3TaZhOw3AaiDY3gLRZrjWOgFfC3jF0VbuuWH7J8qtu+wTzM6v+EfITzCt2vROm3/WAtXqUyjG1ibOeVMsmlk0kQ6n9zUUo8zJhzJXz6Dfk/HJfKi6Nhu9zj2Pbvuh/32Sn2ZFNzhatii1s2SaqmqiKsCU7hy25R8DMAFVdbpaJpAtA/HXFMttEFrYJwtblYCvB4/PK6wQe5x5veLzh8rqTVYBtm1C2NtYFYVtSJNssm9DtgBpxbEotSbiEepfBRAjR2lRg+1cmRCayTFSVn5ldA+sZfbkwDFN+49YQy2sjM1RNr2j6ujJVM8qq3upH25u8vH94TNPZbHZ3N5/Lh9R3GTNLZ7PpNP2KdA3JrL2Z3G2sNHNNpun84VEI0el0/gO0XAQ8dyeK2AAAAABJRU5ErkJggg==" nextheight="1013" nextwidth="1910" class="image-node embed"><figcaption htmlattributes="[object Object]" class=""><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x66a9893cc07d91d95644aedd05d03f95e1dba8af#code">Uniswap V4 bytecode on Etherscan</a>, notice how the contract creation transaction includes both the init code (constructor) and runtime code (smart contract) but only the runtime is deployed on-chain</figcaption></figure><p><em>2. Runtime Code</em></p><p>This is the code that actually lives on-chain at your contract address and runs every time someone calls the contract.</p><p>It’s the part that responds to function calls, reads calldata, interacts with storage, emits events, and does all the real work.</p><p>You can think of it like the permanent body of your contract. The init code is a temporary wrapper that sets it up.</p><h2 id="h-typical-init-code-strucuture" class="text-3xl font-header">Typical Init Code Strucuture</h2><p>A typical structure of a innit code consists in loading the runtime code into memory and returning it.</p><pre data-type="codeBlock" text="PUSH1 &lt;size&gt; &nbsp; &nbsp; &nbsp; // Number of bytes to copy (runtime size)
PUSH1 &lt;offset&gt; &nbsp; &nbsp; // Starting point in bytecode
PUSH1 &lt;dest&gt; &nbsp; &nbsp; &nbsp; // Destination in memory (typically 0x00)
CODECOPY &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Copy bytecode to memory
PUSH1 &lt;size&gt;&nbsp; &nbsp; &nbsp; &nbsp; // Return size
PUSH1 &lt;dest&gt; &nbsp; &nbsp; &nbsp; // Memory offset to return from
RETURN&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Return runtime code to EVM"><code>PUSH1 <span class="hljs-operator">&lt;</span>size<span class="hljs-operator">&gt;</span> &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Number of bytes to copy (runtime size)</span>
PUSH1 <span class="hljs-operator">&lt;</span>offset<span class="hljs-operator">&gt;</span> &nbsp; &nbsp; <span class="hljs-comment">// Starting point in bytecode</span>
PUSH1 <span class="hljs-operator">&lt;</span>dest<span class="hljs-operator">&gt;</span> &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Destination in memory (typically 0x00)</span>
CODECOPY &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Copy bytecode to memory</span>
PUSH1 <span class="hljs-operator">&lt;</span>size<span class="hljs-operator">&gt;</span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Return size</span>
PUSH1 <span class="hljs-operator">&lt;</span>dest<span class="hljs-operator">&gt;</span> &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Memory offset to return from</span>
RETURN&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Return runtime code to EVM</span></code></pre><p>Let's take a look at a typical way of deploying a smart contract on chain.</p><p>Example deployment bytecode:</p><p>6038600C60003960386000F35F357F0DBE671F0000000000000000000000000000000000000000000000000000000014602F5760055F5260205FF35B60045F5260205FF3</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b1abf1fb7262dd5bba24b80747a445ee.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEMElEQVR4nLVVXUwjVRRezWYBaae0nZ0pP521U8pPG5ilU6Z/d9pOS1s6nTItnbYDWhiWlnZAQECBwrIkmmXN7ss+7D6Z7DP74IM+uU++aDDRNW5iWBOMwRgfTYzGB98MvYBa17iJ8eTk5jvfnMx377n3nnuh43+2C8+TZMJN5w7Dc/7vCdDxs0//LtBl7urtt1mtpK3HZiEtFtLS238CrDarraebIMyQtPV0W0gLQRAQ99v7rFby2QLEqZnh1CykZWbhlbG8kJ/OhBMhwIFipQA4bzovFKbHw4lQKMaGYmw6L8RT0VCMBZyXz8Qra9eS46ONAhoNguMmDMM0GkSjQepiZqh0uprOTsgQhNmEmxwDdn/Ah+MmSHV0dMLxz9U7ESAIs16vn58v3b93p1DIxEcjd+/uPdx/QBDExYuXoJhOr4dAo0Eg2drUwnLudhxtQzQGndag0xp1OqNOhxoMz9hkDMNcLnqrtvrOrd3NzZX79+483H+QzY5V5pSpolwuT2fHU4oyMVXMFwqZpaWqUiysvbU9t3s9IsmZclVQZjPVhbj8alye5OW81Ur+ZQVnpTd/8OH+V08/+fa7x0fHnz1+8tHB549++e37w6cfHx4dHB4dfP3Npz/+dHT8w5c//3r8xZNH777/niM4JpTfZNPTnFzNrd8WF2+w0my6VB50UiYcb1zBoJNKVV+PlWrQeXWHV3dipVp0dgOOvLoTnd2AYaxUGy1vjSjr0ZmN4MRyQF4MTiwHJ5Yjyoa0ct0x6MAwrFHAMehIKlWQmwdSJSAvsGcASJWgvAQxDD1C0SMU/ZLqSytAKruFKSBVgFT2pRVPusQrZceAvfEeQAFRfcMvveaXVDY3z+bm/ZJ6OjV5yZMuAaly8tPsnHNEAlLFLc5QoRQVSnnEaxFlzSPOOEey9OgEr6iOQUfjHuD1MzfMUO34ZXMnbiFfFtSaoG5nV28CcTKl3pBW96TVPXFxV1C3k9VNTlazqzfFxd3c+u2wPMfEMyR5xWwydJnQYWagt4c06LSNm2whLYEo62N9gAOAA2EhGRaSnMCz0WBYSC6/XUvkJE7gOYEPJeKcwEfSIkyYXN+dXN/JlBfyK1upmblIWnTFx4dH8/U7URdAjZdRI4phmA5pg44aUaT5pdamljYEaW1qdTEUQXReeuHFNgSBDKLV1kGLtrm5m3L3uSPdlIcKiT00uGKzU6EUHRFPBQjCDDgv4IBjwO5ihgDnDcVYx4Dd7WMAB/rtfbAT9Nv7aIZ2+5h6DqAZethLR/kwzQxhRkM7jppwDEf1OGbs6GjHjToc1f9RIn/Ak8jErjoplvMHoiyfiTM+GrYUmhkKJ0I0QzM+2sUMBaInrSaeigLO62U9Y3nhqpOqH5iT9lAfG8BpiVBYIggMBuM5hgA7swZGh7SdH8d/sud6D/6L/Q7lG2DKy10w7gAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">In our example, the total calldata code passed on the transaction is 68 bytes, but this is divided into 12 bytes for contract initialization and 56 bytes with the actual runtime code</figcaption></figure><p>Let's now look at a step by step code deployment execution.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f0508e5a5f5f53d9b7d409d6c96d1883.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAC4UlEQVR4nK2TW0/bMBTHAyULWZas7CIKgZYNVgleyqegnbTBxkem0KvKA2XjgQcqiurYVhyR3rI2sSfbhV7YBpP46cj9x3HP3+fYUSJK/XbbFwRB4HkeIQQiRAjBAleABK7r8nnXdSDEXHvOCAghvNMOhKgFgO/7jDFlMBxWKpVqtVoqlX5eXBSLxUKhmM/nS6VyPn8sHgti5vjs7Kxardbr9drpabFYqtVq9Xr95KRQqVT4imJR6lKpXC6Xj46Omjc33CAMQyi3hxC3RkhuHInAGMsZhDAhxHVdv91GGPNCPY/XR0i705HlEkJub29lxZ7nBUFAGVMopYwxKuLZoZTyFl1fX7da4OqqgTFuNputVqsfBJTSSMAY8zzv/PzH5eWl7/v9IOj1+r3+OPoTehy9fhiG3CCMoiAIBoLhcDgYDgeDQRRFVBAKAwfCRqMBgHPXv0dwXRcAgDFm4xaJn9EohSCSBo7T6/UopcN/EIZjGUWdbtdxIDeIKL0POiEmDW4E8sCfAsYYAEAIGVUwyjvJhAdlLBgMZKH/BW81pdyAp5s5fcYmK4tm7J+I+CNvEWOs2+0C8Qk6ELYAaLfb7KEHnY1x9X8PfosYYxDBTrfDDyoMO50OQogxFt5vZEZM73GqxIcGVBggcSyu+FYBABDeGdA/XIFHJ6cMZNOjiAbBr/uQl+dZUL7ufzn4vi/j2+EBF4f72Vwum+Wxt5fN5sQoHsV8dvJVTqyUZHO5zw9QOHOKEhNCjIvWwrv3lhqb0/WFeHxRUZR4/KWuz2uaEospr60XhrGgqsrbN69UVVFVRdPmYzH+KhabE1mmMQxD10dhGIaqara9nMmkU6nVT+mNnZ1N205kMumtreR6cmXjw+r29sd0emNzc313N51MrqytJVKpVdtetu2EbSc0TTdNkyeSo2Eq8UmW4vGlJdOyNM0wTcswTF3nQuPepsDiWzFMwzDlGrnMsrgwTUukmOI3e8gwIwTvzZcAAAAASUVORK5CYII=" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>In our example, the process was:</p><ol><li><p>Copy 56 bytes from &lt;contract bytecode&gt; starting at offset 12</p></li><li><p>Place them at memory position 0</p></li><li><p>Return them, this becomes the runtime code</p></li></ol><p>In more complex smart contracts init code can also perform storage intializations, calls to other contracts or even new contract deployments.</p><p>Now you know what happens behind the scene when a contract is deployed. Thanks for reading and see you next Tuesday for more bytes.<br></p>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/f3c83d7f834cf35bc5f4047194bfed15.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Control Flow in Bytecode]]></title>
            <link>https://paragraph.com/@bytecodetuesday/5-control-flow-in-bytecode</link>
            <guid>BmdVqHPHmLgQG2S55paY</guid>
            <pubDate>Tue, 27 May 2025 15:54:21 GMT</pubDate>
            <description><![CDATA[Today, we’re going to explore how smart contracts make decisions and change execution paths using control flow.What is control flow?Control flow is the logic that determines what happens next in a program. In Solidity, you use if, else, for, while, or function calls. In bytecode, those high-level keywords ar...]]></description>
            <content:encoded><![CDATA[<p style="text-align: center"><em>We reject abstraction<br>We believe in bytecode<br>Bytecode is only true form<br>Let’s code with bytes now</em></p><p>Last week, we talked about Stack, Memory, and Storage, the three data regions of the EVM. Today, we’re going to explore how smart contracts make decisions and change execution paths using control flow.</p><h2 id="h-what-is-control-flow" class="text-3xl font-header">What is control flow?</h2><p>Control flow is the logic that determines what happens next in a program. In Solidity, you use if, else, for, while, or function calls. In bytecode, those high-level keywords are translated into jump instructions.</p><p>The EVM is a very simple machine, it executes bytecode one instruction at a time, moving forward by default. But with control flow instructions, we can tell it to jump to a different part of the code, or conditionally jump based on a value.</p><h2 id="h-the-core-control-flow-opcodes" class="text-3xl font-header">The Core Control Flow Opcodes</h2><br><table style="min-width: 332px"><colgroup><col style="width: 282px"><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1" colwidth="282"><p><strong>Opcode</strong></p></td><td colspan="1" rowspan="1"><p><strong>Name</strong></p></td><td colspan="1" rowspan="1"><p><strong>Description</strong></p></td></tr><tr><td colspan="1" rowspan="1" colwidth="282"><p><code>56</code></p></td><td colspan="1" rowspan="1"><p><code>JUMP</code></p></td><td colspan="1" rowspan="1"><p>Jump to a specific position in the code (unconditional)</p></td></tr><tr><td colspan="1" rowspan="1" colwidth="282"><p><code>57</code></p></td><td colspan="1" rowspan="1"><p><code>JUMPI</code></p></td><td colspan="1" rowspan="1"><p>Jump to a position only if a condition is met (conditional)</p></td></tr><tr><td colspan="1" rowspan="1" colwidth="282"><p><code>5B</code></p></td><td colspan="1" rowspan="1"><p><code>JUMPDEST</code></p></td><td colspan="1" rowspan="1"><p>Marks a valid place to jump to. You must jump only to a location with this opcode</p></td></tr></tbody></table><h2 id="h-example-conditional-return-based-on-input" class="text-3xl font-header">Example: Conditional return based on input</h2><p>Let’s say you want to write a smart contract that:</p><ul><li><p>Returns 0x02 if the input is greater than 10</p></li><li><p>Otherwise, returns 0x01</p></li></ul><p>This is what our example looks like in pseudocode:</p><pre data-type="codeBlock" text="if (input > 10) {
&nbsp;&nbsp;return 0x02;
} else {
&nbsp;&nbsp;return 0x01;
}"><code><span class="hljs-keyword">if</span> (input &gt; <span class="hljs-number">10</span>) {
&nbsp;&nbsp;<span class="hljs-keyword">return</span> <span class="hljs-number">0x02</span>;
} <span class="hljs-keyword">else</span> {
&nbsp;&nbsp;<span class="hljs-keyword">return</span> <span class="hljs-number">0x01</span>;
}</code></pre><p>And here’s what the EVM bytecode can be implemented:</p><table style="min-width: 75px"><colgroup><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p><strong>Offset</strong></p></td><td colspan="1" rowspan="1"><p><strong>Bytecode</strong></p></td><td colspan="1" rowspan="1"><p><strong>Description</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p>00</p></td><td colspan="1" rowspan="1"><p>60 0A</p></td><td colspan="1" rowspan="1"><p><code>PUSH1 0x0A</code> Push the number 10 to the stack</p></td></tr><tr><td colspan="1" rowspan="1"><p>02</p></td><td colspan="1" rowspan="1"><p>60 00</p></td><td colspan="1" rowspan="1"><p><code>PUSH1 0x00</code> We are going to load the first 32 bytes of calldata (the program input)</p></td></tr><tr><td colspan="1" rowspan="1"><p>04</p></td><td colspan="1" rowspan="1"><p>35</p></td><td colspan="1" rowspan="1"><p><code>CALLDATALOAD</code> Load the number sent as parameter</p></td></tr><tr><td colspan="1" rowspan="1"><p>05</p></td><td colspan="1" rowspan="1"><p>11</p></td><td colspan="1" rowspan="1"><p><code>GT</code> Check if input &gt; 10</p></td></tr><tr><td colspan="1" rowspan="1"><p>06</p></td><td colspan="1" rowspan="1"><p>60 0E</p></td><td colspan="1" rowspan="1"><p><code>PUSH1 0x0E</code> Destination if <code>TRUE</code></p></td></tr><tr><td colspan="1" rowspan="1"><p>08</p></td><td colspan="1" rowspan="1"><p>57</p></td><td colspan="1" rowspan="1"><p><code>JUMPI</code> Jump to label if <code>GT</code> was <code>TRUE</code></p></td></tr></tbody></table><p><em>False branch (default: input &lt;= 10)</em></p><table style="min-width: 75px"><colgroup><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p>09</p></td><td colspan="1" rowspan="1"><p>60 01</p></td><td colspan="1" rowspan="1"><p><code>PUSH1 0x01</code> Push value 1</p></td></tr><tr><td colspan="1" rowspan="1"><p>0B</p></td><td colspan="1" rowspan="1"><p>60 12</p></td><td colspan="1" rowspan="1"><p><code>PUSH1 0x12</code> Destination to branch merge point</p></td></tr><tr><td colspan="1" rowspan="1"><p>0D</p></td><td colspan="1" rowspan="1"><p>56</p></td><td colspan="1" rowspan="1"><p><code>JUMP</code> to merge point</p></td></tr></tbody></table><p><em>True branch (input &gt; 10) starts at 0x12</em></p><table style="min-width: 75px"><colgroup><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p>0E</p></td><td colspan="1" rowspan="1"><p>5B</p></td><td colspan="1" rowspan="1"><p><code>JUMPDEST</code> Safe jump target</p></td></tr><tr><td colspan="1" rowspan="1"><p>0F</p></td><td colspan="1" rowspan="1"><p>60 02</p></td><td colspan="1" rowspan="1"><p><code>PUSH1 0x02</code> Push value 2</p></td></tr></tbody></table><p><em>Branch merge point, true and false branches converge here</em></p><table style="min-width: 75px"><colgroup><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p>12</p></td><td colspan="1" rowspan="1"><p>5B</p></td><td colspan="1" rowspan="1"><p><code>JUMPDEST</code> Safe jump target</p></td></tr><tr><td colspan="1" rowspan="1"><p>13</p></td><td colspan="1" rowspan="1"><p>60 00</p></td><td colspan="1" rowspan="1"><p><code>PUSH1 0x00</code> Memory offset 0</p></td></tr><tr><td colspan="1" rowspan="1"><p>15</p></td><td colspan="1" rowspan="1"><p>52</p></td><td colspan="1" rowspan="1"><p><code>MSTORE</code> Store the result (either the number 1 or 2) from the stack to memory location 0</p></td></tr><tr><td colspan="1" rowspan="1"><p>16</p></td><td colspan="1" rowspan="1"><p>60 20</p></td><td colspan="1" rowspan="1"><p><code>PUSH1 0x20</code> Return length set to 32 bytes</p></td></tr><tr><td colspan="1" rowspan="1"><p>18</p></td><td colspan="1" rowspan="1"><p>60 00</p></td><td colspan="1" rowspan="1"><p><code>PUSH1 0x00</code> Return offset set to 0</p></td></tr><tr><td colspan="1" rowspan="1"><p>1A</p></td><td colspan="1" rowspan="1"><p>F3</p></td><td colspan="1" rowspan="1"><p><code>RETURN</code> 32 bytes and end execution</p></td></tr></tbody></table><br><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f1a2e65f1a28513e191396aa8d38a7ce.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAACd0lEQVR4nLWUa0+jQBSGh2i6MZusHwig0VQogdblplasRl39V23puv/UNRHbQSBIDBDKbTbDVJdsm03U+GQYzpx5Z85hLoCqquI4jqIojuM8z8MwTJIkTdMkSRBC1YcBeZ7PZrPpdGrbdhRFd3d3nuc9PT35vo8QKsvyowGqqiKZNuumQShrqrcDsiyzbdtxnPv7+yAIHh4eIITz+fxVgRB6fo5ub3/btp1l2VvXDZRlmWVZXlMUBTH+SbYoivl8nmXZOz7i7xI1U17WofduOA7wqQDyQks0Rei9LPaArHLaIM/zZoA8z8nl+A/JEmQSHAAh5HkehND3/SAIZrOZ4zjkEpR1L4RwOp36vu818Gu8VZBJIIQIoUUA13XJHU6SJAxD13WbARzHCcNwZZorSdM0DMPHx0ccgJzOJElI+kEQ+L4fx/HrkS2KAkLoum7wFsjvoCgKgD4ZYE3Gk5vJ5MayJpZ1Y1k/rckvazweD4ej4QiX+hkNF4zqspKlLjxuBFob1Ma39S+brdbG2tfNVm2vU2sUoACuCRQA1Iv9AnZQWAYowkK5aOGu2rW3176+PlPV7mBwdHp6pGnf+32915MvLk3T1I0DVdN6V1cniiJf/hio6n6/r5umcXCoXl0PFLVrmnq/r11cHOuGohv7Z2dHh4ffT06M8/NjTd+XZBGwLKcb+u7urizLkixJkmQYRqcjdrtdURQVReF5XtO17e1tXdf5TkfDqLzAK4qys7PT6/UEgRclURRFQRRkWW6326IoSrKMPYIAuK0tmmZYjmMYlmFxoWmaZVmGYV5rmmY4bov4aYap9djgOI7FcFhUg43aWY/DjT8ivBfIZI80IAAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Step-by-step execution when passed 15 (0x00..0E) as calldata parameter. This number is greater than 10 to 0x02 will be returned.</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fe4e5992cbe7219a67a5787ff9ac586f.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAACk0lEQVR4nLWTbU+jQBDHSUOj5tLE3IuKxjM9KFJ7BLatWp/OU7+UV9Oen9SYay1LykOJFijs0r0sa5GquVOT++WfyTAz7Ay7LDebzXzfn0wmvu/HCHmeF4bhdDoNwpAQMns/SaoMDiFkGMZwOOz3+5PJ5Pb21rZtz/Nc1yWEJEm++CNws9mMTZq3lLmTMJuyEFmcOh/JfwQXx3F/MICm+bvfd1337u4OQhhFUfYyIeTh4eHm5mYwGMRxnDV+6xckSRJFEZoTp/bZzmCMoyiK4/gDO/a0RdnAr89IPnLgjw0Y750tWdz0fzQgL8iWSF7LvpH0DNIGGGP680+nzCKE8mMihMI887IMGnkBQoiwQyaEWLYNIXQcx3FdCKFpmuwSJGnWgNAYDh3HsW3bdhwqRuYs4jiOYRgQQkLIvIFljdM7HIah53kjy8o3ME1zPB7T6x0ELycNGGHIctSdTr37+9FoRBsghDDGQRCk01Mcx/F9H2PMflyMsQGhZVnue7BtezweY4w58p/hur1u75rqqnfV/UXVu+52rjo/n+ik+huXl48FlwvhTqfT4VZKS6XV5dLq8kqp+OkzdUqrS3yR53m+SG2BX6BQKBRYMM3SQqoiFc3MfSaeL3Di18rFxbGm1Q4Pm0dHLV37tr/bqNe3T3/st9ug0VR1fef8vK2qytnZgabV9vb0drvRbGos2G6D3X3t++keAHUA6sfHrVZLPThonJzsAlBXlConCAIAYGtrS1Hk7ZRGo1GtVmu1mizLqqqKogh0fWNjHQAgSZKua7quS5Koqurm5pednZooinJKtVpVFKVSqcgyXUqWZUmSOEFYL5fLgiCsrVEJglAul1OfPjDLCuZ2Lf/4DLZC9qIgCH8AZ3Mbnm0Os0QAAAAASUVORK5CYII=" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">5 is lesser than 10 so 0x01 is returned</figcaption></figure><h2 id="h-do-we-need-jumpdest" class="text-3xl font-header">Do we need JUMPDEST?</h2><p>The EVM doesn’t allow jumping to just any byte, it has to be a <code>JUMPDEST</code>. This design prevents jumping into the middle of data or invalid instruction segments. Think of <code>JUMPDEST</code> as a checkpoint you can land on.</p><p>While marking safe spots for jump instructions is considered a sound and secure virtual machine design choice, the EVM has been rightfully criticized for requiring full 32-byte absolute offsets for every jump. This approach is unnecessarily heavy. A more ergonomic and lightweight alternative would be to use relative jumps based on the current execution point (known as the program counter). In most cases, such as typical if or while logic, the jump distances are small and could easily be expressed in a single byte. The inefficiency of absolute jumps is well-known, and there is ongoing discussion in the Ethereum ecosystem about adopting relative jumps in future virtual machine designs.</p><h2 id="h-whats-happening" class="text-3xl font-header">What’s Happening?</h2><ol><li><p>Input is loaded from calldata.</p></li><li><p>Compared with 10 using the <code>GT</code> (greater than) opcode.</p></li><li><p>If true, we <code>JUMPI</code> to a labeled part of the code where we return 0x01.</p></li><li><p>If false, the EVM continues forward and returns 0x00 and jumps to the merge point</p></li><li><p>The merge point is where both true and false branches reunite and returns the result</p></li></ol><p>Both branches store the result at the stack, then on the merge point a 32-byte value padded with zeros is returned.</p><h2 id="h-try-it-yourself" class="text-3xl font-header">Try It Yourself</h2><p>Modify it and check it using this <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://evmdisassembler-cooldev1337.pages.dev/">EVM Disassembler</a> to:</p><ul><li><p>Return 0xAA if the input is less than 5</p></li><li><p>Return 0xBB if the input is between 5 and 20</p></li><li><p>Return 0xCC otherwise</p></li></ul><p>So far, we've explored bytecode piece by piece, but what does a real smart contract look like in raw bytecode?</p><p>Next Tuesday, we’ll take a full contract and break it down section by section. Subscribe now and see you next Tuesday for more bytecode.</p><p><br></p><br>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/d8abcb42f798d36dae4165b9edd95673.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Stack, Memory and Storage]]></title>
            <link>https://paragraph.com/@bytecodetuesday/4-stack-memory-and-storage</link>
            <guid>PYey4B4k0RMffxWCd343</guid>
            <pubDate>Tue, 20 May 2025 15:41:12 GMT</pubDate>
            <description><![CDATA[This week, we cover something even more fundamental: the three data regions of the EVM. Let’s recall them from the last post:Stack for last-in, first-out temporary values,Memory for intra-transaction data (a byte array that resets every call), andStorage slots for persistent st...]]></description>
            <content:encoded><![CDATA[<p style="text-align: center">We reject abstraction<br>We believe in bytecode<br>Bytecode is only true form<br>Let’s code with bytes now</p><p><br>Welcome back to Bytecode Tuesday. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://paragraph.com/@bytecodetuesday/3-the-ethereum-bytecode-lifecyle">Last week</a>, we saw how your contract gets compiled, deployed, and executed on Ethereum. This week, we cover something even more fundamental: the three data regions of the EVM.</p><p>Let’s recall them from the last post:</p><ul><li><p>Stack for last-in, first-out temporary values,</p></li><li><p>Memory for intra-transaction data (a byte array that resets every call), and</p></li><li><p>Storage slots for persistent state (a mapping of 32-byte keys to 32-byte values).</p></li></ul><p>Now let’s break each one down</p><h2 id="h-the-stack-last-in-first-out" class="text-3xl font-header">The Stack: Last-In, First-Out</h2><p>Think of the stack like a pile of plates. You can only work with the top one. It’s:</p><ul><li><p>Last-In, First-Out (LIFO)</p></li><li><p>Can hold up to 1024 items (each 32 bytes)</p></li><li><p>Super fast and cheap to use</p></li></ul><h2 id="h-some-relevant-instructions" class="text-3xl font-header">Some Relevant Instructions:</h2><pre data-type="codeBlock" text="PUSH1 VALUE → put VALUE on the stack
Bytecode: 60VALUE // Replace VALUE with your desire value in hexadecimal (1 byte)
PUSH32 VALUE → put VALUE on the stack
Bytecode: 7FVALUE // Replace VALUE with your desired value in hexadecimal (32 bytes)
ADD → pop the top two values, add them, and push the result
Bytecode: 01"><code>PUSH1 VALUE → put VALUE on the stack
Bytecode: <span class="hljs-number">60</span>VALUE <span class="hljs-comment">// Replace VALUE with your desire value in hexadecimal (1 byte)</span>
PUSH32 VALUE → put VALUE on the stack
Bytecode: <span class="hljs-number">7F</span>VALUE <span class="hljs-comment">// Replace VALUE with your desired value in hexadecimal (32 bytes)</span>
ADD → pop the top two values, add them, <span class="hljs-keyword">and</span> push the result
Bytecode: <span class="hljs-number">01</span></code></pre><p>Example:</p><pre data-type="codeBlock" text="6002600301"><code></code></pre><p>Which translates as</p><pre data-type="codeBlock" text="PUSH1 0x02
PUSH1 0x03
ADD"><code>PUSH1 <span class="hljs-number">0x02</span>
PUSH1 <span class="hljs-number">0x03</span>
<span class="hljs-keyword">ADD</span></code></pre><p>Let’s now see how the stack is being manipulated in the following step by step animation.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d30500066e305d26b6b6d35b2767f224.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAACj0lEQVR4nJWUXW+iQBSGSe/2om2EDMygLYotaFFoKia6F7vpj1Tb9Lc1abZakQ9TmmgcmGE2iB9o2l365gTnRh7e95w5nCgCCYqbWp+RDDmOe3h4YIyFHx+LZSqMcXagSfKt4iAC5RqSFSgrEJXFSg1VqnIKeHxkjL28vEze3qbTaRAEk8nEcRxK6fcAAs9nxZd4QRBK5yUAwM5BHMdsrWT7/LYDhFCjofb7rX6/dX2tWJbe67UREgaDIWMMY5x+8vqzt79fih4+swMnSZKilDWtqmnVi4qs1i6MZv3s9MdoOGKMRVG0e2P+sKX+B5kCZCRf1ZVOp2nbTUUpm6b263cHwdJgMEgdRCngqJIkC2yjXW57/IEDUWo0VMvSjZt6t2uIIsj3INoCdn9OqSvsup7rea7rzWZuGIYp5isHEEJdq1mmZhhXZluDUJJldHLCjUabiJJ8ypQyxpzZbLFYEEJSPKWe52GMMwb9NKLrq6ptN237plqttNvaz/4tgvznEdEU4Pu+48yCYO77QRAE06kTx3E+qIMpkhGq1y8tSzfbWq1Waeqq3TUAOMumKF6P6fG0ULrKKX17LvSjceCgBOvq5e2tfnfXUNWLm4ba7baAcDocpoD39/fFchkTkhRo8lE+myYjiCxT7/UM09Tu7zuiCErnJY7jnp6eGGPPz8+v4/FyuWSFlWwdbwCiCBCUZAQRlMoykgBAcL+LVhgTQnAUrTAuWJndfZOBIKR7ItsWPA+AACUpcxATMh6P02YGReX7/nTqkPXl2zQZCMJR7QCE0DAMCSHx14rWldfMdfND9S9AFEWvf1593/cKy3Xd+Xyeb/ghAOwBu5tcvL2Zjvb5AUDIOcgAuW1aWIcX7S8GNAwx+r6jaQAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class=""><em>Step by step animation of our Stack manipulation example</em></figcaption></figure><h2 id="h-memory-the-scratchpad" class="text-3xl font-header">Memory: The Scratchpad</h2><p>Memory is like RAM: it’s cleared after each transaction or call. You can use it to:</p><ul><li><p>Store temporary values during execution</p></li><li><p>Return data to the caller (via RETURN)</p></li><li><p>Store arrays, strings, etc.</p></li></ul><p>Some Relevant Instructions</p><pre data-type="codeBlock" text="MSTORE → store 32 bytes at a memory offset
Bytecode: 52
MLOAD → read 32 bytes from memory
Bytecode: 51"><code>MSTORE → store <span class="hljs-number">32</span> <span class="hljs-keyword">bytes</span> at a <span class="hljs-keyword">memory</span> offset
Bytecode: <span class="hljs-number">52</span>
MLOAD → read <span class="hljs-number">32</span> <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">from</span> <span class="hljs-keyword">memory</span>
Bytecode: <span class="hljs-number">51</span></code></pre><p>Example:</p><pre data-type="codeBlock" text="602A60005260206000F3"><code></code></pre><p>Which translates as:</p><pre data-type="codeBlock" text="PUSH1 0x2A&nbsp; &nbsp; &nbsp; &nbsp; // Value to store
PUSH1 0x00&nbsp; &nbsp; &nbsp; &nbsp; // Memory offset
MSTORE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Save 0x2A at offset 0x00, since MSTORE stores 32 bytes and we just push 1 byte (0x2A), the EVM left-pads the 1-byte value with 31 zero bytes to make it 32 bytes. This padded value is then stored at the specified memory offset (in this case 0x00).
PUSH1 0x20&nbsp; &nbsp; &nbsp; &nbsp; // Length to return
PUSH1 0x00&nbsp; &nbsp; &nbsp; &nbsp; // Start offset
RETURN&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Return memory [0x000….2A]"><code><span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x2A</span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Value to store</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x00</span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Memory offset</span>
<span class="hljs-selector-tag">MSTORE</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Save 0x2A at offset 0x00, since MSTORE stores 32 bytes and we just push 1 byte (0x2A), the EVM left-pads the 1-byte value with 31 zero bytes to make it 32 bytes. This padded value is then stored at the specified memory offset (in this case 0x00).</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x20</span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Length to return</span>
<span class="hljs-selector-tag">PUSH1</span> <span class="hljs-number">0</span><span class="hljs-selector-tag">x00</span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Start offset</span>
<span class="hljs-selector-tag">RETURN</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="hljs-comment">// Return memory [0x000….2A]</span></code></pre><p>In the following animation notice how the memory operates based on stack inputs.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fb31e13dfed9cbfb5032540430a7387a.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAACLUlEQVR4nJ2U207iQBiAISVcrtGmc+rQ3QKlItttGoUN8cbEZ1SW4MOJC6Et3YmYSGg742ywxAU5aPe7mOlN58t/LCCEMMEZCCOMMdF1RVEGg4GU8unpaf5KHMfZx0tOCkQnlZpOTUpNqlNi1KlRrSjFleD+/n48Hk8mE8bYeDz2fV8IkU8AAAAaABrUVAAAVFUNIqQoSr/fl1KmaSo3+Y8I9NNm/fLS63Zd2656XrPbdQnRbm97Uso4jsUmuQUYY9M0bLtq2zXDqNTrX1st6+joS6/3S0qZJMnO3z6vLOi63mhULy5a7XbLNA3XbV5dtQleRZDsEXw+bwVCiGWZrms7TqPTcSBEEKJicVWDZEsgpVws4jCcZgRBOJvNDjiWAtuuue7pD8d23VNCMKW0XC7vFAghpJRBEDw/P3POkyQRQkyn0ziO9zlWKep0nHb7u2ka5+dn19c/KYU3N719giiKfD9gjEXRH8aY7/tZs+2LQLcss9mse96ZZZkQIkppqVRab9OXTYQQizXSNP2gBo1G1XEanndWr31TVQ1j/DoHy0F7fHycz+fbrZKjyAAAVdVOTrTjY1VVNYQgIeRtVQyHwyAItl88zIYA/gNlVybIUrRYLDjncR445/sEcF1wd3eXpuloNGJ5iKJoMpmsp/SQgHM+m80452kewjBcb40CAMtHs/NNUCwuBUmSPDz8jqJoNVSfIAxDxti7Iu8QHNimuSr8sWB7m37IO8FfI2gOb7+WHw4AAAAASUVORK5CYII=" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class=""><em>Memory is byte-addressable, but MSTORE and MLOAD operate in 32-byte chunks.</em></figcaption></figure><h2 id="h-storage-the-blockchains-hard-drive" class="text-3xl font-header">Storage: The Blockchain's Hard Drive</h2><p>Each smart contract has its own storage, which is:</p><ul><li><p>Persistent: Survives across transactions</p></li><li><p>Expensive: Writing to storage costs significant gas.</p></li><li><p>Private to the contract: One contract cannot directly access another’s storage.</p></li></ul><p>The EVM storage maps data using 32-byte (256 bits) keys and values.</p><p>So, the storage can be visualized as a map like:</p><pre data-type="codeBlock" text="0x0000000000000000000000000000000000000000000000000000000000000000 → 0x... (32 bytes)
0x0000000000000000000000000000000000000000000000000000000000000001 → 0x... (32 bytes)"><code><span class="hljs-number">0x0000000000000000000000000000000000000000000000000000000000000000</span> → 0x... (<span class="hljs-number">32</span> <span class="hljs-keyword">bytes</span>)
<span class="hljs-number">0x0000000000000000000000000000000000000000000000000000000000000001</span> → 0x... (<span class="hljs-number">32</span> <span class="hljs-keyword">bytes</span>)</code></pre><h2 id="h-why-32-bytes" class="text-3xl font-header">Why 32 Bytes?</h2><p>Ethereum uses 32 bytes words as the native unit for storage and computation. This design aligns naturally with the Keccak-256 hashing, which produces 32 bytes outputs. Since Ethereum relies heavily on this algorithm, for addresses, storage keys, and more, structuring everything around 32-byte chunks makes contract development efficient.</p><p>However, this design isn’t without tradeoffs. Storing small values, like a boolean or a single digit, still consumes the full 32 bytes, which means wasted space and higher gas costs. Developers often have to pack and unpack multiple values manually to use storage efficiently, adding complexity on both smart contracts and dApps frontends.</p><p>The EVM's 32-byte word size made sense for early Ethereum, especially given its focus on DeFi, tokens, and ownership primitives. But as the platform evolves into a general purpose execution layer, the limitations of this native word size become more apparent. There’s growing interest, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum-magicians.org/t/long-term-l1-execution-layer-proposal-replace-the-evm-with-risc-v/23617/33">including from Vitalik himself</a>, in exploring a more flexible, byte oriented virtual machine that better supports new use cases and broader types of applications.</p><p>Some Relevant Instructions:</p><pre data-type="codeBlock" text="SSTORE → write value to a storage slot
Bytecode: 55
SLOAD → read from a storage slot
Bytecode: 54"><code>SSTORE → write value <span class="hljs-keyword">to</span> a storage slot
<span class="hljs-symbol">Bytecode:</span> <span class="hljs-number">55</span>
SLOAD → read <span class="hljs-keyword">from</span> a storage slot
<span class="hljs-symbol">Bytecode:</span> <span class="hljs-number">54</span></code></pre><p>Example:</p><pre data-type="codeBlock" text="602A600055600054"><code></code></pre><p>Which translates as:</p><pre data-type="codeBlock" text="PUSH1 0x2A &nbsp; &nbsp; &nbsp; // value
PUSH1 0x00 &nbsp; &nbsp; &nbsp; // storage key
SSTORE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // storage[0x000…00] = 0x2A, since SSTORE uses a 32-byte key and value, the EVM left-pads the 1-byte value with 31 zero bytes to make it 32 bytes in the same way as&nbsp;
PUSH1 0x00 &nbsp; &nbsp; &nbsp; // key
SLOAD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // load from storage[0x000...00], as SSTORE, it left-pads the 1-byte key with 31 zero bytes"><code>PUSH1 <span class="hljs-number">0</span>x2A &nbsp; &nbsp; &nbsp; // value
PUSH1 <span class="hljs-number">0</span>x00 &nbsp; &nbsp; &nbsp; // storage <span class="hljs-keyword">key</span>
SSTORE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // storage[<span class="hljs-number">0</span>x000…<span class="hljs-number">00</span>] = <span class="hljs-number">0</span>x2A, since SSTORE uses a <span class="hljs-number">32</span>-<span class="hljs-type">byte</span> <span class="hljs-keyword">key</span> <span class="hljs-built_in">and</span> value, the EVM left-pads the <span class="hljs-number">1</span>-<span class="hljs-type">byte</span> value <span class="hljs-keyword">with</span> <span class="hljs-number">31</span> zero bytes <span class="hljs-keyword">to</span> make it <span class="hljs-number">32</span> bytes <span class="hljs-keyword">in</span> the same way <span class="hljs-keyword">as</span>&nbsp;
PUSH1 <span class="hljs-number">0</span>x00 &nbsp; &nbsp; &nbsp; // <span class="hljs-keyword">key</span>
SLOAD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // load <span class="hljs-keyword">from</span> storage[<span class="hljs-number">0</span>x000...<span class="hljs-number">00</span>], <span class="hljs-keyword">as</span> SSTORE, it left-pads the <span class="hljs-number">1</span>-<span class="hljs-type">byte</span> <span class="hljs-keyword">key</span> <span class="hljs-keyword">with</span> <span class="hljs-number">31</span> zero bytes</code></pre><p>As you can see, the memory and the state operate very similarly, the main difference is the memory is addressed by byte pointers while the state by 32 byte slots.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f64888ecb297b5a62a6d1b7eb5a65439.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAABlElEQVR4nK2U207CQBCGaeqdF0SaPXatFGsrGg+kF8bAcwqEp+NiOSYlIYHYJesY2ogVxXSVP3OzyWS+/DOzU6GUMEaLwV1u23a/3weA5XK5Wq3W63WaputMOtNbCeWZFc7JecMVPhc+dwX1AtdrCNuyBoMBAAyHQynleDxOkkRKOZlMSlbfqYIRygIjB2GMUc2hhJ7Ydr/XA4DNZgNfZVR9C+CcXzeDdvv++fkhDP1Wq9npxIzWui9dAEjTVH+VMYAx5te9KLqMooYQIgjqzWZQrZ72MgdKKdOK+wCXu2Hox/Ht09NdGNYfH6/b7U8H6v8AxlgQXMTxjeeJ7TAwZozZlpVvkToKILzyW63I8wRCiBByZABGyHGcs7PatjrGpJwDKL1aFYIxJYQSklcvA9Bavxb0u8stYC9+AWitAWA+n0+n0yRZJEmyWCxGo5FS6pCPA4CPU6EywO4H5IDZbFYESCnNAZaV/2RVcFDE7PqTn6m9hOLTrEWmQ/47QJc+HqVapM1PkBngPzJe0+/H9cfZ7gDvyU8S1tkcG/0AAAAASUVORK5CYII=" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class=""><em>Unlike memory, storage persists after execution and is committed to Ethereum’s global state (in the Merkle Patricia Trie).</em></figcaption></figure><h2 id="h-stack-vs-memory-vs-storage" class="text-3xl font-header">Stack vs Memory vs Storage<br></h2><table style="min-width: 100px"><colgroup><col><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p>Feature</p></td><td colspan="1" rowspan="1"><p>Stack</p></td><td colspan="1" rowspan="1"><p>Memory</p></td><td colspan="1" rowspan="1"><p>Storage</p></td></tr><tr><td colspan="1" rowspan="1"><p>Lifetime</p></td><td colspan="1" rowspan="1"><p>One instruction</p></td><td colspan="1" rowspan="1"><p>One transaction</p></td><td colspan="1" rowspan="1"><p>Forever</p></td></tr><tr><td colspan="1" rowspan="1"><p>Cost</p></td><td colspan="1" rowspan="1"><p>Very cheap</p></td><td colspan="1" rowspan="1"><p>Medium</p></td><td colspan="1" rowspan="1"><p>Expensive</p></td></tr><tr><td colspan="1" rowspan="1"><p>Access</p></td><td colspan="1" rowspan="1"><p>Only top values</p></td><td colspan="1" rowspan="1"><p>Offset-based</p></td><td colspan="1" rowspan="1"><p>Key-value</p></td></tr><tr><td colspan="1" rowspan="1"><p>Use cases</p></td><td colspan="1" rowspan="1"><p>Math &amp; logic</p></td><td colspan="1" rowspan="1"><p>Return values</p></td><td colspan="1" rowspan="1"><p>Contract state</p></td></tr></tbody></table><h2 id="h-hands-on-assignment" class="text-3xl font-header">Hands-on Assignment</h2><p>Write and check using this <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://evmdisassembler-cooldev1337.pages.dev/">EVM Disassembler</a> bytecode that:</p><ol><li><p>Stores the number 42 in memory</p></li><li><p>Loads it back from memory</p></li><li><p>Returns it</p></li></ol><p>Bonus: Can you also store it in storage, then load and return it?</p><p>Bytecode isn’t magic. It’s just a sequence of stack gymnastics mixed with clever use of memory and storage.</p><p>Next week on Bytecode Tuesday, we’ll explore control flow, how to change the flow of execution inside a smart contract. Subscribe now for more weekly bytes and opcodes.</p><p><br></p>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <category>ethereum</category>
            <category>bytecode</category>
            <category>evm</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/782dba2f42baec53ccf4c72176580c67.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[The Ethereum Bytecode Lifecyle]]></title>
            <link>https://paragraph.com/@bytecodetuesday/3-the-ethereum-bytecode-lifecyle</link>
            <guid>5j36fGaaBnfOtlmo2B75</guid>
            <pubDate>Tue, 13 May 2025 16:10:51 GMT</pubDate>
            <description><![CDATA[Today we’re tracing the two distinct journeys your contract takes: one when you deploy it, and another each time it’s called.1. Writing and CompilingYou start with a .sol or .vy file in Solidity or Vyper, defining functions, state variables and control flow in human-readable form. When...]]></description>
            <content:encoded><![CDATA[<p style="text-align: center"><em>We reject abstraction<br>We believe in bytecode<br>Bytecode is the only true form<br>Let’s code with bytes now</em></p><p>In the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://paragraph.com/@bytecodetuesday/2-what-is-an-opcode">last article</a> we explored opcodes, the individual instructions the EVM executes. Today we’re tracing the two distinct journeys your contract takes: one when you deploy it, and another each time it’s called.</p><h2 id="h-1-writing-and-compiling" class="text-3xl font-header">1. Writing and Compiling</h2><p>You start with a <code>.sol</code> or <code>.vy</code> file in Solidity or Vyper, defining functions, state variables and control flow in human-readable form. When you invoke <code>solc</code> or <code>vyper</code>, the compiler outputs EVM bytecode, a linear stream of one-byte opcodes plus any immediate data. That bytecode is split into a header segment, which runs once to set up constructor logic and write initial values into storage slots, and a runtime segment, the permanent code that lives at your contract’s address.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/113124ba723a4527fd30e90763a1c2d7.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAE+0lEQVR4nI2SzW/bZBjAK8rUUpo1bZzYiVOncd58Oc5H7ThOHNtx7Xw4dew4n23X9Ltrm6yZhoBuYgMkJBAI7cJhEqOnSYgDcEAMJC78Adw4c4ADAnGbQOKAhILSDLqyy1799B4ePXp+7/M87xg0PHaQzAXCyShBRQiKirFBP+l2A3whhAPSF4pFo0xE1mhWisTTLiyMosDvjwFAYp5ggsrSjAgAibrBf8CIB4LsZ5WhMZttDoYR4/ZpTj9Sq92i0a1v3BSLO5FsIymtUYwhqVtm7Vjrv1XvvKRWD/jCmrDUzEotTmyFwkpR3Va1PYJQfID3B0Qf4MNEnsvW3W7MarUOBcP3O+BirsFoRw9+GXz59+CLvwZfDQZfDwYffD8IJ8pctsYvrSSS1XhKpzImlSxRyZIXz2CeFOZJoW7a6aY8XtaDZ4Z4WYLMN9tdAPyPBaMOJHlFKe18+92j3/4c/PrH4OdHg9fe+SRILRNkns+tyIVOSlxVjK5ePyovb1G0vsgbi5wez2gxppRk6/FEmWGMBKUFwhJBFk3zqg+Ac8GMDT56+365uv/6nfv37j08Pf3m7t3PmvW+0xElSHkkiEYL0UV1kaukuRpB5iOJ4hkFIqYQZDFM5AlySCgiR+Oqbu7juO9cYHfA5lqfZnVNP5BL2wRZ9IckMl6iWYMgZZarp7maPyB48Yz3bA7ei3jwDA6yo7gHz4SJ/AXB6Bdp2jZFa6LcaTSvm42uJK8vFTYp5rEgyVZxkH0WvGeCir73/w4KpY0ImfcAUchvtJrdVvNao9nDQZaiNWHpCsMYzyjAARcmC2bt4MIOYBhJc1WCUAKElDM6stJpNLuiuOLBM3xuRZQ7zy7w4hmCzBdKnQvfFIYRNj2cRjCiyGbXMPZK6hYvNHHAcdm6JK8/u8CDZ6JxlU5qEITYbHPnghRrhMIKFZX6ewdGrVfR9wVlHfVxSbYmyh2a0Z+uBQICCAj+gPgkOMgmKI3l6jDselIA87nmaETV1uH27q3dzZdPdk8kUlalVbmwwaarLFdnubogtPnciiSvC0Kbyw4jmnG0uXNrfetmZ+fWWueVzd3b9dZxOq2fj+jMA7dXr1N0xQsEglQXYuoP794bPPj8p/fv//jm3RhVyQorDFujGINmTIrWmZQZTyz7gOAP5oJhOUzk/6UAQFZvvf7xw98hCD7vAIKgVEoGvgTq9GNo4AWb971K7dONndPV7Y9aV+bng2405EIDT4KiQRQNIq4gggRGOBA/4grZbQtxarn76ocWi/VxB3aHw4a4XpyzzdgRCEFmHciMHbb56YU47/GTcJS3E5lZp8dqt9sQ56zdMTMHzdods3aH3eHAMBeGub1eN4o6McyFok4UdcHw3MT4GIq6UBSFYXjM5nAG+TKjtehibWGRJ8TluFJJamu0thpVjMVym9ZWqWI9nivHFD2uGHS+EhXLgUwpt1w57m0dHG7u73f299ePDrcODzd6ve1+f29390qvt93pNDBsfsxisaTZxc1OrVkrLWDzUi5jmqquLbVr6rKaM7QlQ5P1MxSZbzTKrYZ23Nt6406/39+9fuPqycm1GzeumqZaKi0VCqJpqu22MbpZlrZYLg93YLFcHh+/ND4+YbXOTU1PX5qYmJycepqp6enJyamx5553Op2xGBEOBwHAeZ6NxQir1To5OWWxWM4yJ0f5FstlCIL+AeyCeCVY9ZepAAAAAElFTkSuQmCC" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">On Remix, you can retrieve the compiled result by clicking the “Bytecode” button on the compiler tab. This will copy both the header and runtime segments to your clipboard. The same result can be obtained with Foundry and Hardhat.</figcaption></figure><h2 id="h-2-deploying-a-contract" class="text-3xl font-header">2. Deploying a Contract</h2><p>Deployment is its own transaction with <code>to = 0x0</code> and <code>data = &lt;contract-bytecode&gt;</code>. That transaction enters the network’s mempool, where nodes check nonce, gas limit and signature. When a block proposer includes it in a block, the EVM executes the header segment: it manipulates the stack, uses transient memory (a temporary byte array that persists only during each transaction) for intermediate data, and writes to persistent storage slots (32-byte keys in the global state). If init succeeds within the gas budget, the runtime segment is returned and stored at the new contract address. For this point forward your contract is now live on the blockchain.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0f2acbb151f52b0c0805cb44693eb269.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAABKklEQVR4nO2TTU+DQBCGZ2FNWz6KJl49GH8DS6sH/2gbUgpFCoYKNY2J9tfoQTxQKrArHGqIMcGPHkzEg+mTJ5vZ05uZyYBhTeaBP/M9z3Vc17GssW2btm1apnFhm3WNka4PB+Z45E3tqTOpu1zeBoGvDwfzILgJw7tFuLi+CmaXnutAFD08Rver5CmOo5Klm02RZwmjKaMpzZ/rZmmcpfEqSZL1+qUo6uZ5Thkry5IxRhnLKX17i6IA5airHCv7JwfCYYcQ9bTfxxjLkiSKovRVSeRbEtqT+LZcF7e7VdGScVVX35agAHC9s3NoCI7jAEBVNUDNwPM8ABDSa7YDQsguYBu7gH8XgBDCGH9/yb8FQqjZAPjIH+3gBx1gjAVB6LzzaeLbAjRNewUh5av7c8mGkgAAAABJRU5ErkJggg==" nextheight="450" nextwidth="800" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Bytecode deployment using the <code>cast</code> command</figcaption></figure><h2 id="h-3-executing-contract-bytecode" class="text-3xl font-header">3. Executing Contract Bytecode</h2><p>Each call to your contract is another transaction with <code>to = &lt;contract-address&gt;</code> and <code>data = &lt;calldata&gt;</code>. Again it joins the mempool for basic validation. After mempool validation, the EVM loads the stored runtime bytecode and runs it with three data regions:</p><ul><li><p><code>Stack</code> for last-in, first-out temporary values,</p></li></ul><ul><li><p><code>Memory</code> for intra-transaction data (a byte array that resets every call), and</p></li><li><p><code>Storage</code> slots for persistent state (a mapping of 32-byte keys to 32-byte values).</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/996bfe4ee32287f392b0bf59c705c1e3.gif" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAFFElEQVR4nIWUXYgbVRTHB0GkL7W1y27bbbWtghYFSxVFsC9CH7S++UmttAURFYuK+CAUrJ8UxAcfWpEqFaxdu/1Y3JbgNuwmnWabbeJmk9lMJntnJjO58z13Mh+ZZDKZfIxMUlehFA8/7pw7w+F/5txzLrZtdNv4mtExbP0ItnYdtnbT2NYtY5s3j24aX7/p/nXj2zds3Xj3yNhd993OKLZ+uI5g9z73xJ5dD+7GMOzhjQ89uvmRJ3c89vj2nTtGtj2wYRzrtDqe3TBYRaclBUgKIxlV3RQMBYhikReLvEpJ2opSV+qrNFBjleHW4k0bml7N02nVYGVH1uqyI2RYOS9gtm1rSC9Dia9CyLI0wxbpSomtWrb9X7xWq9H0XNcFACzl8wWiSBBFkiwRRDF6UFSBKJYBTTPsfPpmIZcT9Zosq0v5PHZmYurn0xMlis7nSct2er2+73faQafX63c63eEaBB1ZVmqWIxt2zXJEUeK5qqbpHMcjhCiqbJqmaSDIMoHf0hTFazYgx9kG4jkeW7iZm0uk5tPZxLV5SVZct+G6jWaUbHMVp+5SVFmUVQAVtWbJskJRZYQMCAVV0wmCIMrshdn0T+cvTyayU3Ppy6nFyRn81MWZxQKJAUBP/zGdSOCxWAzHcYoCqqbXTPNfjCg/123YtuM6dcu0TNOxbKdmmpbtaMjq93qnrlzHXvhgzTvHsb3vY4e/xF77FDv0Obb3yNc/TmArTHWZZH49ezY+i6+A6gqoMhWZqUgAQIYVGVbIlWGqWEmT3JBkgRFVq+60LNtzHM91W5bZ9Lyg43e8Rrvb7vpeEDVOo93v9StsFVPhMpU9h/95MnPtdGnxYjE7WRpQvPn7cnaimD1XyJxfTE/kMpO5hcnF9MRf6QmQnwL5SxVyukTMEIX4ciFO5ad5KqZVU6sg4YYAZiXIYKbGCmBWADhPzfLUrFCeu+VEL5OrSHRCohMKm5ToOQEkeSou0YnKCk5TKXZlngdJhcVrYnYVBDMKd0MWeezIiUvYnvdOXkjMX88uk2wmS2Syy/Ppgq7bvt/xvOBOuK7fdH2v0W4OHNf1HScqmuN4hlEHgFOUGtJNjBPU5CJxPZ2ZuXo1Ho/jOK5pOkLIig7YRMgY+Fa0MR3TMC3Tcmynecu8IUNr3WYIGZjvtRYKObxApBeysVgskUgSRJFhWMhRUFEBYAYNKlFVUVANiZdEUbJtJwzDXq8fhmGnG03JndA1hFmmI8kqQkbNqAVBEIZhMJiymmHSZcAw0WwDQDM0Q1EUAICiysMBJskSSZYgFHy/fSciAdt2aEBDKCBkuG5j+KHf67OCGLuRomhaVTSEDFXT2QonQIHjeI7jIRREURpG/c8f2LYDALBte5i777e9lh+1sKpeJUjRsFRFhVCQZSUIOuE/NqzPIKQ7vFqGNJotr3WbAMOwoig1m94wqNvthmEoqcoSQZQoKoUnY7FYPB4vl8sChJqmIYRqhmGZtSBoB347KmmnEzl+e6i9KhAdct12ETJkWbFth+eqJbJEM5WqorOClityWYIBPBJlXRLlIglohhdFpcJWqTKXIyorjGg2W8hwqsg2O0GKE7H9nx387rcwDP2B8C0BCAUIBWcgsJQrFMlSRbKSycm5K18kpo+eOP7i/o8/fOXQ6+8eeOrwq0+/vG/33md3fvL2M1M/vPTLt/uOHT74zVdvnjl24PRbHx19/o17tuz6fhrvR1dyJKBp6G8BK4ntBE1CPgAAAABJRU5ErkJggg==" nextheight="450" nextwidth="800" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">In Etherscan, you can see the bytecode passed calldata on every transaction. The calldata are the parameters passed to the runtime code.</figcaption></figure><p>Storage in Ethereum is organized using a data structure called the Merkle Patricia Trie, which is a specialized form of a Merkle tree. This trie efficiently encodes key-value pairs (such as storage slots or account data) into a compact structure where the root hash represents the entire global state. Every time a storage slot is updated, the corresponding MPT changes, resulting in a new root hash that reflects the updated state.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2b1b71040957e22941a693db6fd7d422.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACKUlEQVR4nM2Uoa+jQBDGSVDoFU2aVCCaIFasIKlAbIJpgkRUYhGIFStqESvWPFGBRiAw/QdqKmqraxBrKjBjMAgMl2NeyeXlmteXd3e5TxDYnZnfzkdmrfEvy/pfAMNDXdfhyx8GjOPY9z3nPE3T11NeBQzDUJZlURRSyjzPi6Ioy/LFJl4CAIDruoSQ9XrteR6ldL1eA8B3AbPXAEAptR6ybZsxhoBP/8cnHfR9f7/f67rOJslJWZYJIY7H4/1+77ruax30fW+MAYDT6YTl8jy/XC4AMJ90GAYAuFwueZ7v93sp5el0AgBjTN/3TwGYr5Qik2zbRjeklPPubAg+pZRomuM4i8WCEKK1nnefAjabDSHEsizP83zfz7LsQ878KYSglC6XS9u2KaVBECilngJQt9tNSsk5932fcy6EuF6vz/y9Xq8YzBgLgkAIcbvdfmMRetp1nTFGT2qaZhzHpmmUUofDoW1bDMCcrusAoG3boiiUUli0aRqttVLKGIMB2MdPQFVVnPPdbrdarVzX5ZyjlWmaRlG0WCw8z4vjmDHWTmKMxXGM5kRRhLOtteacu667Wq3iOOac13X9DtBae54XhqFlWRiEOWEYBkHAGLMsK4oiQogxpmkaQsh2u3UcZ7PZBEGw3W7xNHg4LEIpfXt7ewecz+c0TcVDSZJUVYXgbNK8DpOSJMFpQGG7VVUlSSKEwHFJ0/R8Pv/D63q+jX8d/Q+LX11HwA+wlWTZ4fxUNAAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Ethereum rely on Merkle-based trees where the root hash represents the entire global state. Currently the Merkle Patricia Trie is being used, although there are ongoing discussions about transitioning to more efficient structures like Verkle trees in the future.</figcaption></figure><p>During contract execution, each opcode consumes a certain amount of gas. If the transaction runs out of gas, all changes made during the call are reverted, this includes the stack, the memory and the storage. But when execution succeeds, the changes to storage and the emitted logs are emitted. The state of Ethereum then updates in the following flow: the old state root and the calldata (which you can think of as input parameters) are processed by the contract’s runtime bytecode. This produces an execution trace, which results in a new state root. The updated root reflects the global state after the transaction and is used in the block’s final state commitment.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cf174d0983459751ca37c44eb6189b54.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC7ElEQVR4nLWUz0vcQBTHB5bSiwjtitriwYOCXiterFAqVLzoRf+hLXgTIrgHYRVhve3N/6DKetplcQ2BoAkhCZMJmcQ4GTKzTFIsZnSpv6rY9nMYwvDyvrzve29A7z8Dno3ICsQD5P0/EPB9HyGE7xKGIYQQY/ysxp8EhBBpmrquG0WRbduO49gFjuO4rosQghBmWcaf4I6AeAJCCOd8d3e3XC5PTk5MT09OTU1OTEwMDw9vb28zxjjnfbvuIYS4EeCcJ7cQQvofjDFK6cXFRaVSAQCUy+/Gxj6Mj38cGioDABRFYYwJITDGCCHf94MC3/flTRzHQgiQZZnneY7j9L2WEa7rQggppZqmeZ7XarU6nc6Pgk6n0263Lcvyff/q6sp13bOzM4RQ3z3LsiCEnudlWQaEEEEQaJp2fHzc7XabzaZhGM1m8+TkRIYGQaCq6tZWtVarKcqmomzWarVqtdputzHGeZ5DCA8PD3VdPz09bbVauq4fHR2Zpun7/rWArABjHMdxkiQYY0JIGIYIIV3XoygSQmxsbAAABgZKpRIolcDg4BsAwPr6uhAiSZJutyvHIU1TSmmSJHmeU0rlCFwLQAgZYwghTdNUVT0/P7dtm1KKEErTlBBycHCwuPhtbW11ZWV5ZWV5bW11aWmx0WjEcex5nuu6hBDDMDRNOymQP94RCMMwiqJ+G8IwlG3gnEMIOedxfJkktHDYTRJKSEIpVVWVMQYhlE7KPssktm0jhG56QAiBEPp3keNPi5IbjcbMzKeFha/z85/n5uYWFr7Mzs5Wq1WZIk3T5DHkKlyP6VODnGUZIaTX6ynKJgBgdPT90NDgwMDbkZF3AIBK5Xt/oR7doRdtMqU0iiJd13d2duv1fUm9vr+3V9c0LQzDfqLXPBVyB23bxhhzzgm5xDi4uMU0Tcdx8jzvvwqvEej1eoyxuCAIAsMwTNO0LMswDMuyKKV/W8E9f38W5Hkuz2ezv0jgdx4+ls8K/AIEu+rUzN1M5wAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Ethereum steps during execution.</figcaption></figure><h2 id="h-4-consensus-and-finality" class="text-3xl font-header">4. Consensus and Finality</h2><p>Upon successful execution, the node calculates a new state root, a Merkle Patricia commitment covering every account balance and storage slot. That root is embedded in the block header. Under Proof-of-Stake, validators propose and attest to blocks; peers re-execute the same bytecode to confirm the state root matches, then follow the fork-choice rule and finalized checkpoints to agree on one canonical chain. Once finalized, your deployment or function call is irreversible.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cc69acd60b11626bb437982b565b123d.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACsUlEQVR4nK1UTWgTQRgd9SDtxZMUL1KkBwUvVkoLBYOIomcpFUTbQxXpxYsgKMGecpBCLjmULqyBHBK3DlOyMnTawZXBweDQQgMt0rQhabNx0klSo0iRCpXsxE1s9dQ8HsPszH7f2+9vgdtOFPL5XCtd1wVtdP91p/bj+67P2s63dgpIWXrycjww0nvjweD1scFrY/0jz4by+VzbBIpu8XgvAMcA6ALglLfpBusb6w2Bzb/hm23+57z1yst1cXllefT5UN/whcDI5cD9S33D528/vtmIQEqplNKrUqparfpelAfpQe8PnJe2S0qprcLmUlpUyzuVctWnUuV6DZRSnHOEEGOMerAsK5vNSimz2SxCiFLqOA6lFCHkOI72yzm3bZsxtrCw4DiOYU6vrq1KKSvlygGNugDG2LKsYDBoGEbMQyaTqdVqWiASiYRCoagHSmnNg/4ObWKaZiKe2FjfkFLi929nycwsmbHfIUSsj4sf6gKEEM65XoUQEEKMsRDCtu1YLMY5p5QKITjnsVgslUoJIaamphhjhBDvcREiKBY/LaUF6AHgLADnPHaB/jsX6wKUUtu2LcuKRqMYY18AY2yapr4yDIMxpgVSqZRhGAghCKF+ASVRU6D7kIDOZjweD4fDjDEIYWuKOOeTk5OmaTLGMMY6RTpcy7JCoRClNDmbXPuccd1Ccv4NnEvAuQQir+FcvJEizjmEkBBCKdX18IsMvWh08SGEjuPojtIm+pyQecOcXllN7+3u7f/ab/LnfqVcabapj8Nt2oo/c9sw0W1a/FJYSovwq9BY8O74xOj4xOijiXsvIk+bk3zkQXNz+dyJPgA6ATjjDXMnAD0tk3x0bJfUrYdXTg6ArqudpwMdHQOgd6gn18Z/keu6W4WtXD7nU0fcToGiWzzANgv8E78BbI9ZAoaBaHcAAAAASUVORK5CYII=" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">After execution is computed, validators reach consensus on what is the new state root. The new root is attached to the next block header.</figcaption></figure><p>Now that you have a clear, step-by-step view of deployment versus execution and how each leads to a consensus-backed state, you’re ready to dive deeper into how contracts are constructed at the bytecode level. Subscribe here on paragraph and join us next Tuesday for more bytecode.</p>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <category>ethereum</category>
            <category>protocol</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/5f6436dc165bca2f3d3114a581a51dc3.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[What is an Opcode?]]></title>
            <link>https://paragraph.com/@bytecodetuesday/2-what-is-an-opcode</link>
            <guid>5EzXgwAWxw28j6EMFDGH</guid>
            <pubDate>Tue, 06 May 2025 16:00:18 GMT</pubDate>
            <description><![CDATA[This week, we're going a level deeper: Opcodes.What is an Opcode?An opcode (short for operation code) is a single instruction that tells the EVM what to do. Think of it like a Lego block: each opcode does one very specific thing...]]></description>
            <content:encoded><![CDATA[<p style="text-align: center"><em>We reject abstraction<br>We believe in bytecode<br>Bytecode is the only true form<br>Let’s code with bytes now</em></p><h2 id="h-welcome-back-to-bytecode-tuesday" class="text-3xl font-header">Welcome back to Bytecode Tuesday<span data-name="handshake" class="emoji" data-type="emoji">🤝</span></h2><p>Last week, we talked about <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://paragraph.com/@bytecodetuesday/1-introduction-to-evm-bytecode">EVM Bytecode</a>, the raw machine level code that the Ethereum Virtual Machine (EVM) understands and executes. This week, we're going a level deeper: Opcodes.</p><h2 id="h-what-is-an-opcode" class="text-3xl font-header">What is an Opcode?</h2><p>An opcode (short for operation code) is a single instruction that tells the EVM what to do.</p><p>Think of it like a Lego block: each opcode does one very specific thing. When you put a bunch of them together, you build a working smart contract.</p><p>Each opcode is represented by 1 byte (2 hexadecimal characters), and each one corresponds to an operation like:</p><p>Storing data Loading data Adding two numbers Returning a result Jumping to a different part of the code</p><p>Some opcodes are followed by parameters or data, depending on what the operation needs.</p><h2 id="h-lets-look-at-real-bytecode" class="text-3xl font-header">Let's look at real Bytecode</h2><p>Let’s take this snippet of bytecode: </p><p style="text-align: center"><code>7F00000000000000000000000000000000000000000000000000000000000000105F5260205FF3</code></p><h2 id="h-what-does-this-program-do" class="text-3xl font-header">What does this program do?</h2><p>In plain English:</p><p>It pushes the number 16 (at the end of the PUSH32) to memory position 0 Then, it returns 32 bytes of memory starting at position 0 This includes the number 16 we just stored, followed by 31 zero bytes</p><p>It's a simple program that always returns the same 32-byte value (number 16 in decimal), which is composed mostly of zeros, except for a 0x10 (16) at the end.</p><p>We’ll break this down into opcodes and understand what each one does.</p><h2 id="h-dissecting-the-code" class="text-3xl font-header">Dissecting the Code</h2><p>We'll read it left to right, 1 byte at a time (2 hex characters = 1 byte)</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0ce9e1a20462106ecdb6caef253a862d.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACp0lEQVR4nL2UPWvbQBjHBZkkXJxwhSMClxsODDcciObCpS6o7WCaEEEyBMeFVhBDTAOhjVznpditRTEW1BhRNBjq4kEUjw6oW0CLdw8ZvKSfIR8gU4kuUdyXhNI0+Q3Hc3d/3f+e50EnJW8Y6bYN5IjL1HK0JcsyACCeXv3trwaqqkIIhTRWy2PnCiRJmpiYAADEMgCAqqrC+FIDWZabzWan0zk4ODg+Pt7b25MkSdf1IAj6/f5wOAzDsNfr+b7f6/WCIPB9fzgcjkajwWAQhmG9Xvc8D0J4lYGu69vb27Ztd7vdQqGAEFpYWPA8z7Isx3GWl5c3NjaaEY7jxIFt24ZhaJpWLBZVVR0v1IWBLMsYY0opxhghlEqlMMaaphFCEEJiEZ+DImIlQiidThNC0uk0QujPGQAAKKXsZ7QI9hfESkrpeCek8evHuuvAGBtP4iIDQsg/HEcp/T0eT+LUQJZlQoiu67FIjCJf7fxeca1EY8Q653z87mLknGOMRavPDCyrNBgMOOee552cnBQKBUJIp9MZjUaMsSD41u/vU0r9CM4f+L5/eHjIGGu320dH3xljvv81DENN0zzP6/f3df0RAFNnBhhj03zuuq35+aerq8/a7bZlvTYMo9n8aNv2zMx9121Z1hbns67b8rxPuv7QdVvd7udMZs6233e7Xxhj9fqHavVtJjNXLK47Tt0wFkUnJAghY6xaedNovDPNfCp1L5t9XC5vLi0tmmYeIcT5bKVSqtV2TDO/u/uqVtvJ5VbW181KpZTNPjHNfLm8yfns1tbLRqOay61UKqVGo7q29oIQAiGUAAAQQkVJKEoimZyMfve7ipKIujQpXo54V1HuiCCKzzSKkoj+3smo6KdTUf3p6enTRyV5PQCYErW+jFt/rv+7wQ/kuzXMg1qYpgAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Bytecode is interpreted left to right, 1 byte (2 hex characters) at a time</figcaption></figure><p>Initial Stack: The stack is empty at the beginning.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0f14ff8b2e4c9a1162f5fe21a7b880d6.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABzklEQVR4nK2UX4vqMBDFW0IIYUga7Z+kqa22W2uVi6tLWdjv/1Xqg4gVH6ygVJcqK5cLC3LtIQ9DHubHnDOJAQCWYJZgTDBgbc04ozcBAEJIKVVVVdM0dV0fDofj8Xg6neq6Pp/P1ydkWD3m6n5fWn1pCcdydb/nijuAUvoA7Ha7sixXq9V6vd5sNmVZ7vf7pwCEUkIIA6Bt9XPaOwIAGGOl1Ha7vV6vl8vlmY7/AjjnSsnlcvz5OS2KvCjyaOgXRc4Yy/N4Pn+TUt4BTdNc/tKzAErpjWEr5WgtXdcGAMfpAYAQAoC+OoEQQin5/j5eLidfX3/C0DdN1BrUGkUNw3wVAACc8yCQUeRHkR+GPmMA0K7QY4u2L2YgpVwssjSNFovs4yMjhJomQgh3A2CM2XZvFOskGQyH2nXtIJDDoQ5Dn9JuJhCe56VpOJ3Gk8lIa3lbnnGWjTqzyHHsNB2kaZjnsdaeYZgI4S4tchx7FPtZNppOY8+zMW5b33NGrwOEEK7rzudpkgxms6QoZpyz+5J2GLKdJIMgkGkajscRY3B/BN0AyE2miTHGCCHTRI+frhsAvTVqLW+Ltu4eQH9RZxn8Js45IURrXVXVfwO+AdHfWlV6dzL3AAAAAElFTkSuQmCC" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Opcode 7F (PUSH32): Pushes the next 32 bytes onto the stack. These bytes represent the number <code>0x0000000000000000000000000000000000000000000000000000000000000010</code>, which is 16 in decimal.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3a2a3a187c317c4b8ca525812c8ab792.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACJ0lEQVR4nK2UzW7aQBSFx5pY09F0Ljb+GTNgY1vGARRRRLJqHzabrPMG2eUpcJNNzAJZOIrEj5TIUNkoLapCigpHs7ir+ebcufcgxlhN47w6jFc1MFqJMYYxdhwnz/OiKJbL5WKxWK1Wr6+vy+Xy7e1tc4BQTeeWrBtOzRA13QRL6nUL3gH0N+D5+TlN08lkMp1OsyxL0/Tl5eUgAKWUEEIoEEKrwwihjFZV6UB1HGc2m202m/V6fciNfwM0AFM4yB2i4Ar5l8gfndke8i8p42eyi+SFI0ReAYqiWO/oUACjFAAMy6pbdl2Ir7pJGSdanTL2BXRE+NEONM1xxPBb53IU//h+4XmOouCyRZQwSrGifALYNbQPjxhjANBsinZbel7DdRuMlVPEKuHqk49yAABCiOEwjiJvOIxHo5gQqigYY/VzwHw+/1np8fExSZKnp6cPX4A454ah+4EMw1a7LS3L2Lpx3QalHwO2RZZlt7e319fXd3d3Nzc39/f3HwMANNu2o8jt9YLzc19K0e0Gg0Enjv3PHSwWiyRJxuPxw8PDeDze6wAATNOIolYUud1uIKWNkIKx+s8WHaiyRaZp+EEjjv1eL7BtQ1XLqxn7ExWzY6ZI0zTLsgaDKAxb/X54ddUH4OVq72TR7EgHhmGEYavZFFHkdjoe52VanAxAKimKqqoqxlhR8DbpTgag7zu1jc9tcWIA3aOT/cE+AQAhREqZ5/l/A34BQmZPIsV+zE8AAAAASUVORK5CYII=" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Opcode 5F (PUSH0): Pushes the constant 0 onto the stack (Equivalent to PUSH1 0, but with gas savings).</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1971d70362063de10c6be8144f5ab3d0.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACUklEQVR4nK2Uz2siMRTHZwghhJCY+ZkxzvhjdrQqrLRd99ff20LPBemxl1IKPfZUqmKhepAyiodRaDu6RNnCLuq6u37J4eUd3of3vi/RCCEZTjOcUk4JVTFlFC9FCAEAeJ43Go3SNJ1Op0mSzGazl5eX6XT6+vq62EFaxqCONE2RMUWG2xlHmobDVwCM8TtgPB73+/3BYDAcDp+fn/v9/mQy2QmAMEYIEUIQwkhdlkflVBJC6HleHMeLxWI+n+9S8XcAY8zzxKfj8tdvtS+fD5rNar6QbTarlNJqtdRofBBCrABpms63aj2AEMwYY7ZrOq4hhGGalBLLMgghnHNC8P92wDm3hafJj5p/pBW/a0aAoQbVhJQHmqZvAiRJ0u12e73e4+Njt9sdDAabOiCcMT8ngrwM8lk/8CglhKgVet+i+FfAKhgOh7e3t61W6+Tk5PLy8u7u7u3tbb0HQojDw0o5yh8dlY+PKwhhXQcAwD8CLi4uWj91fX2dpukaAKXUsoxiSYahXyhIx7FyOVEoyCDIYrwNEMfx+fn56enp1dXV2dnZzc3NWpM0xrjrulEU1Gqlg4OilGK5POVKpbipg5WSJGm32/f3951O5+Hh4enpaROA2bYVRX4UBdVqSUpX03QA4JYR/ZXUiGzbKpaylUqxViu5rgWhKr3yGWwF7PQOOOeO4zQaURj69XrYbNYZo6sl3VsHlmWFoZ/LiSgKyuU8perb2BsALaXrEEIIANB18P7T7QeAl4XUyFWg4v0D8AbtzYNNYowhhKSUo9HonwE/AObaR9gG0UxQAAAAAElFTkSuQmCC" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Opcode 52 (MSTORE): Pops the top two values from the stack and stores the second value at the memory location specified by the first value. In this case, it stores <code>0x0000000000000000000000000000000000000000000000000000000000000010</code> at memory location 0.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9cddeea1e4c87415dff6c329d61423f2.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACfUlEQVR4nK2Vy0+jQByAIROCs5MZpuUxQEsfSAk2m0Zd4mX3z/aoF23isWrj0Rs+KCnGJqUGF7oBVtPoarrqFw6/cJiP32vgEEISxRLFmGKEixgTDEsQQgAAXdfjOM6yLEmS+Xy+WCzSNE2S5PHxcbkGnFTDqlmvM6nOJKpIqlmvqbQSQAifBXd3d0EQXF1dhWEYRVEQBPf392sJRAhFUcQIwSJ6eop3IkJIEARd16fT6XK5zPN8nRNfCgghus52dnp7e1u+7/m+12obvu9hjD2vOxhsMsYqQZZl+QrrCiCEhBDGZKYruslURUYIyXINIUQpRQh+NgOJUl1nu9uO/8P99fO73WY8D4oCFYWCHMd/VoAQwoQIivmNtTa01oZqoYJyhp6m6FMCSiVVY1xjm9N6XHObs3aBAAEPABC+RoAxluXapm3YdnOzazCt3miwdtu0LAPCL8mAUE3THMfqe13X7ZgmK4en57qd1UVbPk3RfwsIIYoiO07TcSzP65qmxnE8AMJXlkhR5E7XcN3O1lZX02RBKI5G6O9VwRiLSy4vL6MoerEN71M1maqqOhg4tt3s923f7xOCqyFdLVGe50mSLBaLj2Qgy7JtNxsN5jhWr9fCGFVLsFqi2Wx2c3MznU7DMLy9vQ3D8Lokepc0Tblyp0SeFwRBAADwPHi+6SqBYRhhGI7H49PT0/39/cPDw+Pj44ODg/Pz8/F4nKZplmW/X5Fl2Xw+n0wmxVVRVhyVQRH/U3BxcTEajY6OjobD4cnJyXA4PDs7G41GURRVHXrNZDKJ47gQvMWqYDabVd/1zMPDQxAE1e/hLfI8L3rwFoQQURRN06z24GNj+gewe0UFXx9OHgAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Opcode 60 20 (PUSH1 0x20): Pushes the byte 0x20 (32 in decimal) onto the stack (length of the data we want to return).</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1ed312ae647acd1424c94de1fd855178.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC10lEQVR4nK2VTU/iUBSGW2ttmpvbD/rdAjKEIuAnkWHir/UXuDOudCMkrgwqcSOwso6UpjUSW0ylZUI7MKhgyMw8aZOzaZ97+p57iwAAaAbSDIQMBHBcQwqSEQAADMNkWXYcJwgCz/Nc1x0MBr7ve5739vY2WgKEZqGgJhISnZBohqcFNcEKzFSAomgseHp6Mgzj4eHBNE3LsgzDeH5+XkpAkCRBEBAAclxNrugmSRLHcVmWbdsejUZhGC7zxo8CiqJkWSqX9Wq1WKkUKpVCOq1Uf2xubuZEkdvby21v502zNxqNgiAIZ1hWQJJk5OBkmVdVSRA4AADPsyxLQwgBAJqm/FMHDMPIsrS7q5fLGwcHW6mUgqIYEUGS4wwkSXIcZ65gtqFFegQAQFGUpknpdSWdVlIpBQDwO+LJFP2HDKr7ejGfrO7r3/fzDLlG4gggVr8WvLy8tCe0Wq37+/u5K0AghAzLrgjf1qQMLq6vMeIar66K6VUhBQA5VxAX3W63VqsdHR0dHh6enJxcXl4Oh8O5GdC8ICJCDpGLiFRAWQVTN5DUNqbkpwInyiCeoumTrut2Op1Wq3V3d9dutw3DmN8BRVE8zxX1ZEFPbpUymibiKAKIFZJY+T8ZQAh5nlvPqHo+UyxmBZHHMCLOORZI0RQ5jtPpdCzLmt0NwXs+DFW8oPGYCoKws5PLZpOlUrZSKVEUjGb03VkUhqHneYPB4G864Dgum01qmpTLpXQ9DSGI3v9HYNt2v99/fHy0bds0zW63a5rmzwjrS3zfR+I9haI4juMYhqEoFp9CU4GiKKZpNpvNq6ur4+Pjs7OzWq12enp6c3PTbDZ93w+CYPiJIAhc1+31eshkS8UffVzPFdze3jYajfPz83q9fnFxUa/Xr6+vG42GZVlxQp/p9XqO44wFi5gV9Pv9eF1TXl9fDcOIfw+LCMNwnMEiKIoiCEJV1UVn0TIh/wLEHjwFy7nFgQAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Opcode 5F (PUSH0): Pushes the constant 0 onto the stack.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b4416d62a7e7a42b330b1b2ab5e39854.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC7ElEQVR4nKWVX0+bUBjGIYwRcnIopaUHqFC1tcVtams6F79vv0ATLoxRL7Rq4g3axsREyW7olJLW2Ag1WOgCzKbO1j/bk3PxhgR+5zzv8x4wAECChQkWQhYCGNaQgXQkAABBEIIg9Ho93/dd13UcZzAYeJ7nuu7j4+PoHcISSchLHIcSHEqw6QQvcUmejQE0TY8Bt7e3pmm2223LsmzbNk3z7u7uXQCKpimKggDQYfW0wmcUAIAkSUEQut3uaDQKguA9X/wbwDCMIKBKZWljY7laVatVVcmJ1aoKIVTVhdXVPEIoBvi+H7yq6QCapiNGShDSkoR4PgUASKeTAACWZQGg//cELMsKAlpbW6pUSpub32RZxHEiNCg0isYwfBbAcRzDMH5GMgyj3W5PBwAAGIbJZpGiiIoiyrIIIQAgjNA4Rd3ngLiwLOvk5ETTtFqttre312w2h8Ph9B4ghMrlYqGglMvF9fUiRdE4ThAE+SZga2tL07R6va5p2uHhoe/7UwAQwiSXzM1LC/k5JSfyfCqbRbmcJMsiTb8BODo6qtfrtVpte3tb1/VZJ2ARynwpZle+5laXFTmbKYXhWSoW5ycHbfSUovGb9/f3hmFcXl5eXFxcXV2Zpjk1BaFFLMdhmUK4RPUzJxI4RhDkKxZ9SBgTWpTG0gu4WMJEFYMIUJ+iBv+5KhBCvUiGYdi2PTkN/nNNnYzQokyGr5YLpYJUWVn48V1lGBiHdNKiIAhc1x0MBh/bf9zkVCq1uDgnSSiflwsFBUIQD8GkRf1+//r6utvtWpZ1c3NjWdavSPar8jwPi2aKwnGSJEmCIHCcGN90MUAURcuyWq3W6emppmm7u7sHBwc7OzvNZrPVanme5/v+8IV833ccp9PphFdFPFNREdZTAefn57qu7+/vNxqN4+PjRqNxdnam67pt23GHXqrT6fR6vRAwS5OAfr8f72ush4cH0zTj38MsBUEQ9mCWGIahKEqSpHgO/i2mvwGoOTPozxd02QAAAABJRU5ErkJggg==" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Opcode F3 (RETURN): Pops the top two values from the stack. The first value specifies the memory location to start returning data from, and the second value specifies the size of the data to return. It returns 32 bytes starting from memory location 0.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/bcb58ccf2524c56ff94a9f623f112e3f.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACeUlEQVR4nK2V20/iQBSHS7rd2cnJlNKLMx22XKRA2XgBw5rs/+2jviiJj6jER9/qamlaIwnF1G3ZlK4uwWiI+mUeTvow38yZ30kFACgqpKgQohAgWU1kghcAgCiKjLEwDJMkiaJoOp3OZrM4jqMoenx8nK+BUCwRg6sqLaq0qOhFg6slQ8kFGONnwd3dneu619fXnuf5vu+67v39/VoChDFCiADgrHpa2TcEAJIkMcaCIJjP52marrPjqkCWZcZor9fc3+/0+06/71SqZr/vEEIcp76z06CU5oIkSdIl1hVgjBcOjTGdc2oYGgDoegkAFEUBwB+9gaIojNHd3Wav1/71a8uyzEJBzBqUNQoLQuGjAgCQZblcppWKWamYlmUSAgBZhJ5TFHzwDSil3W7Ltivdbmtvr4UQLhREUZQ+R0AI0bRSrc43N79Xq9wwtHKZVqvcskyMP+cGysbGhm1bnU693a5xThfhabZateVBmz+l6B0CWdc127Zs23KcOuNUEAqiKH1mi3RdazbMTru2vVUvMxVJ2db5O4uiSCkNF1xdXfm+vzINb/MvpiXdEPi2YDQE9kOo/vxGlHyal1uUpmkURbPZ7B0tIiVVlegm0vlX1vhiNjGQFUEQBJPJ5ObmJggCz/Nub289z/u9wH+TOI6FxUwhkASMJCyJWfFELjBN0/O80Wh0dnZ2cHBwdHR0cnJyeHh4cXExGo3iOE6S5M8LkiSZTqfj8TjfDhZruVgVXF5eDofD4+PjwWBweno6GAzOz8+Hw6Hv+/kLvWQ8Hodh+P+8L1kWTCaT/FzPPDw8uK6b/x5eI03TLEWvIcsyQohzns/B+2L6F1gJRQdXFKwwAAAAAElFTkSuQmCC" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The returned data is <code>0x0000000000000000000000000000000000000000000000000000000000000010</code>,  the number 16 in decimal notation.</p><h2 id="h-understanding-the-flow" class="text-3xl font-header">Understanding the Flow</h2><p>Stack Operations: The stack operates on a Last In, First Out (LIFO) principle. Each opcode manipulates the stack by pushing or popping values, which are then used in subsequent operations.</p><p>Memory Storage: The MSTORE opcode stores data in memory, which is temporary and used during contract execution. In this example, the number 16 is stored at memory location 0.</p><p>Returning Data: The RETURN opcode allows the contract to return data to the caller. It specifies the memory location and size of the data to be returned.</p><h2 id="h-assignment" class="text-3xl font-header">Assignment</h2><p>Try using our online <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://evmdisassembler-cooldev1337.pages.dev">EVM Disassembler</a> to break apart this bytecode yourself.</p>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <category>evm</category>
            <category>protocol</category>
            <category>ethereum</category>
            <category>solidity</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/1f18a6108b6407fafafa619a200e40cb.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Understanding EVM Bytecode]]></title>
            <link>https://paragraph.com/@bytecodetuesday/1-introduction-to-evm-bytecode</link>
            <guid>nKzTnEID2vZKAumkPoWh</guid>
            <pubDate>Tue, 29 Apr 2025 16:00:00 GMT</pubDate>
            <description><![CDATA[Explore how Ethereum smart contracts run behind the scenes. Learn what EVM bytecode is, how it works, and why it matters—even if you're new to blockchain. No jargon, just clarity.]]></description>
            <content:encoded><![CDATA[<p style="text-align: center"><em>We reject abstraction<br>We believe in bytecode<br>Bytecode is the only true form<br>Let’s code with bytes now</em></p><h2 id="h-what-is-bytecode" class="text-3xl font-header">What is Bytecode?</h2><p>Bytecode is a low-level version of your smart contract. It’s what your Solidity code turns into before it gets deployed on the Ethereum blockchain (or any Ethereum compatible blockchain , a.k.a EVM compatible blockchain).</p><p>Think of it like this:</p><p>You write your contract in Solidity (a human-friendly language). Then the computer translates it into bytecode (a machine-friendly language). This bytecode is what the Ethereum blockchain actually understands and runs.</p><h2 id="h-what-is-the-evm" class="text-3xl font-header">What is the EVM?</h2><p>EVM stands for Ethereum Virtual Machine. It’s like a global computer that runs on every Ethereum node. Whenever someone deploys or interacts with a smart contract, the EVM is responsible for running that code.</p><p>The EVM doesn't understand Solidity (or any other smart contract language) directly. It understands bytecode, a set of very simple instructions, kind of like a recipe with tiny steps.</p><h2 id="h-the-evm-stack" class="text-3xl font-header">The EVM Stack</h2><p>The EVM uses something called a stack to do its work. Think of a stack like a pile of plates. You can only:</p><ul><li><p>Push a new plate onto the top, or</p></li><li><p>Pop the top plate off.</p></li></ul><p>You can't reach into the middle. You always work with the top of the pile.</p><br><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/95348e71adb89a99db600cb3702ab81a.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADD0lEQVR4nLWU72ujSBjHIzJ4qZk0bn60m9Ldo0257t7CvlnY/7vvSmnQUInEUaxo7IQktSkVIRZDGpugRA+d1O3edm8pd/d5MYwPOl+f+T7PU2AYhoVbLNzagkWmmO4BA8rlsmVZSZIEQfD4+BiG4Wq1CoJgvV4nr6RQKm+92d3erpe26yXIld7sbpe438rlcr/fv7+/v7m5cRzH8zzXdW3bDsPw1QI0ADRNFxkG0IBOHwBVoPIM1q//5b8LsCzbaNQ+f259/frx6Ohd6+gdhCzLQiIQRVH8jCRJ8s2PhGG4WCyCICDrcrlMBQAALMvW65WdnWq1WqlWKwAACOHPMohfOp0EXdfVdd2yLIyxYRij0SgVgBA2GrVPnw6/fPmjdbT/8c/DSiVN4UWBOI4dx3Fd92cCpmmKonh2dmYYxng8juO4wDAMhGyz2djf3y2mMDRN5x6sMohMFEWr1cr3/el0+jy4XC6jKEqSxHEcRVEQQp1OByE0GAw2HtTrtePj34+PD6gnSBUlSeL7PsaY3CbGuNvtiqIoZdi2Te7dsqz5fJ4kiWmaPM+LotjJkCQpFSgWixzHHRzstVr7e3s7zWaDyfrAMAzP8+7u7lzXnUwms9nMNM32E4IgDIdDz/Nub2/JC9PpVNd1nucvLi4EQeh0Ot1ud5NBrVY9PGx++HDw/n3z7ds6wwCO4yRJ0jRNlmWe5y8vL80MWZYlSer1eoqiYIxVVdU0rd1uq6qKENI0DSGkqqooiqqqyrKc9UFGYQNFUTRFURzHIYQMwyDf6LqOMR6NRoqikEM1TbNtW8+QZZlsdF0XBCHPoNfrbcoUAMAwgElJV+IBMXk2my0Wi4eHB2LjwxNBEBCHfd8PgmA+n6/Xa9d1iT0IIUmSNiaD7yECEELi7dXV1WAwGA6HpGYmk8lVBqnUMAx1XR+PxxjjKIo8z2u32ycnJ6enp+fn59fX12mZvijwfFTE33fWj52cR/JG6/f7pmluGu2XAsk/ks+PfFTkfBsV/0Yg+RX/v0A2Hr7BsiwAaR/8VwJ/AZl1y9U6XME+AAAAAElFTkSuQmCC" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><h2 id="h-how-instructions-work" class="text-3xl font-header">How Instructions Work</h2><p>In bytecode, everything is done by combining simple instructions. You push values onto the stack, then use an operation like ADD to do something with them.</p><p>Here’s a small example:</p><p>Add: 2 + 5</p><p>To add two numbers together, the EVM needs to:<br></p><ol><li><p>Push the number 2 onto the stack</p></li><li><p>Push another 5 onto the stack</p></li><li><p>Run ADD to add the top two numbers</p></li></ol><br><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2b0534217a786b1653d8de7846c0e8a1.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACcklEQVR4nLWT7WvaQBjAK+HI4nnxhZp2gpRBJ/tSipb+1YKCtIUi/WBELLWKSk1EWhsDGiNRiiSXYLhkmIBrtZs6tt+n5CF5fve83AFN0xAFIQoGEUMzy2dAA5ZlRVF0XdcwDIzxYrGwLMswDEKIuycHITYYOw6H46FwPISiodjXSCjyhWVZQRCm0+lgMBiNRpqmjcdjSZIWi8XeAgoAiqIYmgYUWEKBQIBaVUD2P/K6AELIcYfn56eXlz8uLlIn3xLJJLcS2LbtvGPt583IJwIAAIQwHo9wXIzjYiyLEAoihLZW4OyQfSlACHHc4dnZaTqTSmdSJyeJZPL4zy1yvNSz2azX623t4cFyiyA8OoolEhyEDMPQFLU+A8dxCCEYY9u2/aBlWaZpTiYTf8f8oGmaq5b+EnjZuXTmezqTYhiGopYz36yAEPL8/Kyqquu64/G4Wq0Wi8Wrq6tSqdRqtfzPXl9fFUX5ZAaUh7dDgKbpQCCwJphMJoqiaJqmKIqqqrIs8zx/fX2dy+Xu7u6azaamaf42q6o6HA4xxh8E71kTOI5j23az2eR5PpvNFovFer0uimKj0bi9vS0UCpVKRRCETqfD83w+n7+5uanVarIsr0a1XUAIEQSh0WiUy+X7+/t2uy3L8tPT08PDQ7lcfnx87HvU6/VqtVqr1Vqtlt/JnQTEa5Ft229vbxhjwzAsy3JdF2M8n89N09R1nXjM53OMsa7rpmmuz2CrgBDS7XZ7Hrqu+zvabrf7/b4kSf5JJUl6eXnpdDqz2ez9LdlJ4LN5mTdfN2/frgLnN9m3OvaowP0r/r+A+QiEEAAQjUb/leAnpf/qE5w4P4kAAAAASUVORK5CYII=" nextheight="900" nextwidth="1600" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><span data-name="eyes" class="emoji" data-type="emoji">👀</span> What’s happening on the stack:</p><table style="min-width: 75px"><colgroup><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p>Step</p></td><td colspan="1" rowspan="1"><p>Stack New Value</p></td><td colspan="1" rowspan="1"><p>Description</p></td></tr><tr><td colspan="1" rowspan="1"><p>Start</p></td><td colspan="1" rowspan="1"><p>[]</p></td><td colspan="1" rowspan="1"><p>Stack is empty</p></td></tr><tr><td colspan="1" rowspan="1"><p>PUSH1 0x01</p></td><td colspan="1" rowspan="1"><p>[2]</p></td><td colspan="1" rowspan="1"><p>2 is pushed</p></td></tr><tr><td colspan="1" rowspan="1"><p>PUSH1 0x01</p></td><td colspan="1" rowspan="1"><p>[2, 5]</p></td><td colspan="1" rowspan="1"><p>5 is pushed</p></td></tr><tr><td colspan="1" rowspan="1"><p>ADD</p></td><td colspan="1" rowspan="1"><p>[7]</p></td><td colspan="1" rowspan="1"><p>Top two numbers of the stack are added and replaced by the result: 2 + 5</p></td></tr></tbody></table><p><br>This is the foundation of how smart contracts work under the hood. Bytecode may seem basic, but when you combine lots of small instructions like this, you can build powerful and complex contracts, all without touching Solidity.</p><p>Click that Subscribe button for weekly bytecode learnings.</p><p>Let’s reject abstraction together.</p>]]></content:encoded>
            <author>bytecodetuesday@newsletter.paragraph.com (Cooldev1337)</author>
            <author>bytecodetuesday@newsletter.paragraph.com (filosofiacodigo.eth)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/c5c6a52f91cd9f271aec321510e2a83b.jpg" length="0" type="image/jpg"/>
        </item>
    </channel>
</rss>