<?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>rustboot.eth</title>
        <link>https://paragraph.com/@rustboot</link>
        <description>Trying to learn about and build a decentralized world</description>
        <lastBuildDate>Fri, 24 Apr 2026 11:38:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>rustboot.eth</title>
            <url>https://storage.googleapis.com/papyrus_images/6ba13817a682ce0f0e087693c59d3ef642c1170fb3ba3f4a4b66a6ea331be00e.png</url>
            <link>https://paragraph.com/@rustboot</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[A Techincal Overview of EOF (Ethereum Object Format)]]></title>
            <link>https://paragraph.com/@rustboot/a-techincal-overview-of-eof-ethereum-object-format</link>
            <guid>W1qYOhBw5XvABBZn2xir</guid>
            <pubDate>Tue, 15 Oct 2024 05:45:36 GMT</pubDate>
            <description><![CDATA[EOF or EVM Object Format is a proposed set of upgrades to EVM(Ethereum Virtual Machine), planned to be included in the upcoming hardforks. It standardises a way to encode the bytecode of a smart contract in a more structured manner. Its one of the biggest changes to the EVM since the genesis of Ethereum. In this article we shall go through the current way in which the bytecode is structured (hereafter called legacy code), the problems it has and why we need EOF and how EOF solves some of the ...]]></description>
            <content:encoded><![CDATA[<p>EOF or EVM Object Format is a proposed set of upgrades to EVM(Ethereum Virtual Machine), planned to be included in the upcoming hardforks. It standardises a way to encode the bytecode of a smart contract in a more structured manner.</p><p>Its one of the biggest changes to the EVM since the genesis of Ethereum. In this article we shall go through the current way in which the bytecode is structured (hereafter called legacy code), the problems it has and why we need EOF and how EOF solves some of the problems of legacy code.</p><h2 id="h-what-do-we-have-currently" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What do we have currently?</h2><p>Before we can start with changes EOF brings, we must first understand how the current legacy system works. We&apos;ll be using this following contract and its bytecode as example in this section.</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

contract BaseIncrement {
    uint256 num;
    
    bytes32 constant digest = 0x04485b22a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d;
    
    bytes32 storageDigest;
    
    function increment() external {
        storageDigest = digest;
        num += 1;
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> 0.8.21;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">BaseIncrement</span> </span>{
    <span class="hljs-keyword">uint256</span> num;
    
    <span class="hljs-keyword">bytes32</span> <span class="hljs-keyword">constant</span> digest <span class="hljs-operator">=</span> <span class="hljs-number">0x04485b22a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d</span>;
    
    <span class="hljs-keyword">bytes32</span> storageDigest;
    
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">increment</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        storageDigest <span class="hljs-operator">=</span> digest;
        num <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
    }
}
</code></pre><p>Its a very simple contract which has storage variable <code>num</code>, <code>storageDigest</code> and a function <code>increment</code> which when called increments the storage variable <code>num</code> and stores the constant variable <code>digest</code> as <code>storageDigest</code>.</p><h3 id="h-current-solidity-code-format" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Current Solidity code format</h3><p>When you compile this code, you get the following bytecode which is deployed.</p><pre data-type="codeBlock" text="deployed byetcode - 6080604052348015600f57600080fd5b506004361060285760003560e01c8063d09de08a14602d575b600080fd5b60336035565b005b7f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d6001908155600080548190606a9084906071565b9091555050565b80820180821115609157634e487b7160e01b600052601160045260246000fd5b9291505056fea264697066735822122093ad1a84e1cc5f50d88cb85b1f30eb2db6a5e64558983cd6e8e5b4623c3df29f64736f6c63430008150033
"><code>deployed byetcode - 6080604052348015600f57600080fd5b506004361060285760003560e01c8063d09de08a14602d575b600080fd5b60336035565b005b7f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d6001908155600080548190606a9084906071565b9091555050565b80820180821115609157634e487b7160e01b600052601160045260246000fd5b9291505056fea264697066735822122093ad1a84e1cc5f50d88cb85b1f30eb2db6a5e64558983cd6e8e5b4623c3df29<span class="hljs-type">f64</span>736f6c63430008150033
</code></pre><p>When this function is called at runtime, the execution of the bytecode starts from the beginning and continues until its stops execution by the <code>STOP</code> opcode, or reverts or the code ends.</p><p>If you have good knowledge of the EVM and how to read byetcode, you can compute through the above bytecode and be able to split it up into sections as follows</p><pre data-type="codeBlock" text="Function Dispatcher- 6080604052348015600f57600080fd5b506004361060285760003560e01c8063d09de08a14602d575b600080fd

Increment code logic- 5b60336035565b005b7f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d6001908155600080548190606a9084906071565b9091555050565b80820180821115609157634e487b7160e01b600052601160045260246000fd5b9291505056

Data section containing ipfs hash, solidity compiler version etc- fea264697066735822122093ad1a84e1cc5f50d88cb85b1f30eb2db6a5e64558983cd6e8e5b4623c3df29f64736f6c63430008150033
"><code>Function Dispatcher<span class="hljs-operator">-</span> 6080604052348015600f57600080fd5b506004361060285760003560e01c8063d09de08a14602d575b600080fd

Increment code logic<span class="hljs-operator">-</span> 5b60336035565b005b7f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d6001908155600080548190606a9084906071565b9091555050565b80820180821115609157634e487b7160e01b600052601160045260246000fd5b9291505056

Data section containing ipfs hash, solidity compiler version etc<span class="hljs-operator">-</span> fea264697066735822122093ad1a84e1cc5f50d88cb85b1f30eb2db6a5e64558983cd6e8e5b4623c3df29f64736f6c63430008150033
</code></pre><p>The first is the function dispatcher segment, this looks at the function signature in the calldata of the transaction and routes the execution of the code to the relevant part of the bytecode. Second is the bytecode for the <code>increment</code> function.</p><p>Lastly, the third section of the bytecode is just metadata about this contract, it contains things like the solidity compiler version, ipfs hash of the compiler settings etc. The third section is generated by the solidity compiler automatically and attached to the end of the bytecode. This helps verify the contract and in code analysis.</p><p>This third data section is never executed, the bytecode is set so that all executions reverts or stops before reaching this section of the code.</p><p>Keep in mind that this way of adding metadata to the end of the contract is just how solidity adds metadata, other EVM smart contract languages like Vyper might do it differently. It is not a standard, the code will run perfectly fine even without this third section. The metadata can be placed in between actual executing bytecode as well, it doesn&apos;t only have to be in the end.</p><h3 id="h-push-and-immediate-arguments" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Push and Immediate arguments</h3><p>Before we go to the next section, it is vital to understand push opcode and immediate arguments.</p><p>Push is a opcode used to push a certain length of bytes after it into stack memory. We don&apos;t have to go into stack memory here. All we need to understand is push opcodes have arbitrary arguments immediately after it in the bytecode, and these can be anything. These are immediate arguments.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/721567e71ac520c027036dbb2c09acfad9427a83f780c0524d4b6def1ce0edc1.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>In the above picture, the highlighted bytecode <code>60</code> is the opcode for Pushing 1 byte to the top of the stack. And the highlighted bytecode <code>80</code> is the bytecode which will be pushed to the top of the stack. This 1 byte of data can be any byte.</p><h3 id="h-jumpdest-analysis" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Jumpdest Analysis</h3><p>The compiler compiles the code in such a way that according to the calldata input given the execution has to jump back and forth between different parts of the bytecode. For example in the function dispatcher section from above, once the function selector in the calldata is determined it jumps execution from the function dispatcher section to the section containing the increment logic.</p><p>It happens at</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0833dcd713a78b835a9cdfa6a307a5c71869049390e9bdee09ba74946175493c.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>When the function selection in the calldata is correct only the bytecode highlighted in green is executed, then it jumps to the section containing the logic. To stop the execution to jump to arbritrary parts of the code, the EVM currently only allows jumps to the jumpdest opcode. Jumpdest opcode is <code>5b</code>. That is the EVM only allows jumping the execution to where it contains <code>5b</code>, like shown below.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a0dbbea21d4b8701ae28a6abe107ca4fc2677155d3128ef2ec57f31320fd8f78.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>After the execution of the function dispatcher section highlighted in green, the execution jumps to the jumpdest opcode <code>5b</code> at the start of the increment logic section.</p><p>So does all <code>5b</code> in the bytecode denote valid jump destinations?</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/12ce672158b9a555ae625cad0d81e5febe8db5029068c627c21242135d4e0bf1.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The answer is no. Not all 5b in the opcode can automatically be considered a valid jump destination. Because as we saw in the previous section on PUSH opcodes and immediate arguments, any byte can be add to be pushed onto the stack using PUSH. And the third <code>5b</code> in the bytecode shown below is not valid jump destination but part of the immediate argument for a PUSH32 opcode.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fd855d37d995982c13a6d7847058dbcb54f36fee6cc4f06a60569d4524a09ebb.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>As you can see in the above picture, the PUSH32 opcode and the red highlighted <code>5b</code> is part of the immediate argument for it and hence not a valid jump destination.</p><p>To avoid problems arising from the edge case, ethereum exectuion clients like geth and nethermind etc, do something called a <strong>jumpdest analysis</strong> which analyses the bytecode before every execution to find the valid jumpdest opcodes. This is an extra computation which might slow down the execution of transactions.</p><h3 id="h-allows-arbitrary-hex-to-be-in-bytecode" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Allows Arbitrary Hex to be in Bytecode</h3><p>Currently, there is no validation during contract deployment time to ensure that all the hex in the bytecode is a valid OPCODE or immediate argument accepted in the EVM. There might be invalid opcode in the bytecode and it will not throw any errors during runtime as long the execution jumps/avoids the invalid opcodes. But the problem with this current approach is that it makes it really hard to make upgrades and changes to the EVM, as it might make these invalid opcodes valid. This can breaks existing contracts.</p><h2 id="h-why-do-we-need-eof" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why do we need EOF?</h2><p>As we saw in the above sections the current EVM is not perfect and has certain drawbacks we would want to overcome. By adding EOF support we can have</p><ul><li><p>Upgradeability of the EVM</p></li><li><p>Code and data separation</p></li><li><p>Eliminate JUMPDEST and replacement it with code sections</p></li></ul><h2 id="h-how-eof-works" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How EOF Works</h2><p>Henceforth in this article, we&apos;ll be referring to the current EVM as legacy to clearly differentiate it with the proposed EOF changes.</p><p>In the Legacy EVM, all the bytecode deployed in assumed to be valid and is executed serially from the beginning of the bytecode till the end or until it reverts or execution stops. There is no validation of the code during runtime and no enforced code and data separation.</p><p>In EOF, the concept of unstructured contracts is replaced with <code>containers</code>. These <code>containers</code> are structured bytecode which contain the version of the EOF it runs, the number and size of code sections it has, the stack inputs, outputs for each code section and also a separate data section which can contain etc.</p><p>The EOF container is structured as</p><pre data-type="codeBlock" text="container  = Header, Body
header := 
    magic, version, 
    types_section_id, type_section_size, 
    code_section_id, num_code_sections, code_sizes,
    [container_section_id, num_container_sections, container_section_sizes,]
    data_section_id, data_section_size,
    terminator
body := types_section, code_sections, [container_section], data_section
types_section := (inputs, outputs, max_stack_height)+
"><code><span class="hljs-selector-tag">container</span>  = <span class="hljs-selector-tag">Header</span>, <span class="hljs-selector-tag">Body</span>
<span class="hljs-selector-tag">header</span> := 
    <span class="hljs-selector-tag">magic</span>, <span class="hljs-selector-tag">version</span>, 
    <span class="hljs-selector-tag">types_section_id</span>, <span class="hljs-selector-tag">type_section_size</span>, 
    <span class="hljs-selector-tag">code_section_id</span>, <span class="hljs-selector-tag">num_code_sections</span>, <span class="hljs-selector-tag">code_sizes</span>,
    <span class="hljs-selector-attr">[container_section_id, num_container_sections, container_section_sizes,]</span>
    <span class="hljs-selector-tag">data_section_id</span>, <span class="hljs-selector-tag">data_section_size</span>,
    <span class="hljs-selector-tag">terminator</span>
<span class="hljs-selector-tag">body</span> := <span class="hljs-selector-tag">types_section</span>, <span class="hljs-selector-tag">code_sections</span>, <span class="hljs-selector-attr">[container_section]</span>, <span class="hljs-selector-tag">data_section</span>
<span class="hljs-selector-tag">types_section</span> := (inputs, outputs, max_stack_height)+
</code></pre><p>note: In the above block <code>,</code> is a concatenation operator, <code>+</code> should be interpreted as “one or more” of the preceding item, and anything within [ ] should be interpreted as an optional item.</p><p>The <code>Magic</code> is the 2-byte long unique identifier to establish that this is an EOF container. The <code>EOF Version</code> is 1-byte defining the version of the EOF used in the container.</p><p>The <code>Headers</code> define the type, number and length of sections in the body of the container. There are multiple types of sections which can be defined in the headers.</p><ul><li><p><strong>Types Section</strong> - Contains the number of inputs, max stack height of a code section and whether it is non-returning.</p></li><li><p><strong>Code Section</strong> - The sections actually contain the code which is run during execution.</p></li><li><p><strong>Subcontainer Section</strong> - These sections contain bytecode of contracts which are to be deployed by the container.</p></li><li><p><strong>Data Section</strong> - These sections contain arbitrary data, which might contain the compiler version and other metadata about the container</p></li></ul><p>The <code>Headers</code> are followed by a header terminator of <code>00</code> to denote the end of the headers and beginning of the sections. The sections are arranged in the order of Types, Code, Subcontainer and Data.</p><p>The headers for the <em>types</em>, <em>code</em> and <em>data</em> sections are mandatory.</p><h3 id="h-eof-structure" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">EOF Structure</h3><p>All EOF container must start with the magic and version, The magic as proposed in <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-3540">EIP3560</a> is <code>EF00</code> which is 2 bytes long. The version of the EOF should be 1 byte long. An EOF container starts as follows-</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cf274012c2ca0078519f724bc27aeda28f512ca30c613ee1cb8c2ee361b86fa6.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h4 id="h-headers-of-the-container" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Headers of the Container</h4><p>After the Magic and Version the headers begin. The first is the header for the types section. The id for the type section header is <code>01</code>. The Id is followed by the length of the type section in 2-byte.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7cdad2afc22bff8cb351eec1410e9592d341391c5ace3d0e19b53164d228c585.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>From the above section we know that the type section has length of 4 bytes.</p><p>The code section header is added after the type section header.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8ec206d6f55e8e2e45363317aea3759f0c27283dd96270660981c098e1077153.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>As you can see above, the id for code section header is <code>02</code> and its followed by 2 bytes indicating the number of code sections. Which in turn is concatenated with 2 bytes containing the size of the code section. If there are more than 1 code section, the 2 bytes for the sizes of each of the code sections is concatenated.</p><p>Next for the subcontainer header,</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1cca84a2c6f08b1a9a3ee937f0af067b75004d2971b4093ea0a321d1d3988e19.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>As shown in the above diagram, the id for denoting the subcontainer header is <code>03</code> and it followed 2 bytes denoting the number of subcontainer section. After that, 2 bytes denoting the length of each of the subcontainer sections is added.</p><p>Finally, at the end of the headers is the header for the data section</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1fb18ce22a06e08278e6854f895f0805af6b4a35301160ad849c3ef5bf0da8c8.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The id for the data section is <code>04</code>, which is followed by 2 bytes denoting the size of the data section</p><p>The Header is terminated with <code>00</code></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2807c5f8ce06ded6b3f1c6af97433ad7bc6bcba4acced7b7dd484619cfb08d04.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Now that the headers are done, after this point in the bytecode, the body of the container begins</p><h4 id="h-body-of-the-container" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Body of the Container</h4><p>The body of the container contains the actual content of the all the sections defined in the above headers.</p><p>The sections are arranged in the same order the headers are, that is types, code, subcontainer and data sections.</p><p>The type section is added as follows</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/037e4963bb13272c705d125dfb887683409509054a684003eda6a5e53ffd9e56.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>As you can see above, the type section defines the number of inputs(1 byte), number of outputs(1 byte, <code>0x80</code> if its non-returning), and max stack height(2 bytes) of all the code sections. In the above example since only one code section is specified in the headers only the number of input, outputs and max stack height for one code section is present in the types section.</p><p>The types section is followed by the code section,</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/994ba705663aa90d9158394a294249bc42edf907391ca40c0570c67e371413b5.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>As defined in the header, there is only one code section and it is of length 4 bytes.</p><p>This code section is where the actual bytecode which is executed it present. In EOF, <strong>the code sections can only contain valid opcodes</strong>. This <strong>validation happens during deploy-time</strong> and if some <strong>invalid opcodes are detected the container deployment is reverted</strong>.</p><p>Due to this validation only currently valid opcodes can be present, and in the future new opcodes can be added without it breaking previous contracts.</p><p>Also another EIP in EOF, <strong>removes support for JUMP and JUMPDEST in EOF container, and code execution can only jump from one valid code section to the beginning of another code section. Hence JUMPDEST analysis is not needed before runtime</strong>.</p><p>After the code section, the subcontainer section is added to the container. <strong>The subcontainer section consists of the bytecode of the child container/contract the parent contract has to deploy</strong>. For example, a factory contract which creates other contracts, contains the bytecode of the deploying contract in the subcontainer section.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5445798e22de457721e215feca7aff31b7326cdf805a26bdfbbb01a79aab4924.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>As shown in the above image, the subcontainer contains the EOF bytecode for its own container. <strong>Unlike the other sections the subcontainer section is optional</strong></p><p>After the subcontainer section, the data section is appended,</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b1ed0832c3643ef7c6618ff8460b8c950a6d2ea800d9318ff978117c17842e2e.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The data section can contain as arbitrary bytecode which might contain more information and metadata about the container.</p><p>You can more examples EOF containers and how they are split <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ethereum/evmone/blob/master/test/unittests/eof_example_test.cpp">here</a>.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>Now we have an brief understanding of the proposed EOF upgrade to the EVM and how it is to be structured. I hope this article has helped you better understand EOF.</p><p>I&apos;ve attached other resources I used to learn about EOF in the References below. Give them a view as well if you feel some of the concepts in this article are not well explained.</p><h2 id="h-references" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">References</h2><ul><li><p>Rareskills Blog on Solidity Metadata- <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.rareskills.io/post/solidity-metadata">https://www.rareskills.io/post/solidity-metadata</a></p></li><li><p>Uttam Singh&apos;s Youtube Video on EOF- <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=3-bAWOBemyc">https://www.youtube.com/watch?v=3-bAWOBemyc</a></p></li><li><p>Ethereum Cat Herders Youtube Video on EOF with Danno Ferrin - <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=rlZwPuF149U">https://www.youtube.com/watch?v=rlZwPuF149U</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://evmobjectformat.org/">https://evmobjectformat.org/</a></p></li><li><p>EOF container Examples- <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ethereum/evmone/blob/master/test/unittests/eof_example_test.cpp">https://github.com/ethereum/evmone/blob/master/test/unittests/eof_example_test.cpp</a></p></li></ul>]]></content:encoded>
            <author>rustboot@newsletter.paragraph.com (rustboot.eth)</author>
        </item>
        <item>
            <title><![CDATA[NestJs Unit Testing]]></title>
            <link>https://paragraph.com/@rustboot/nestjs-unit-testing</link>
            <guid>rWeLETimOccLqxKmPOKx</guid>
            <pubDate>Mon, 08 Apr 2024 11:30:25 GMT</pubDate>
            <description><![CDATA[Unit TestUnit tests in NestJs uses Jest under the hood. Your test file should have the extension fileName.spec.ts the spec specifies that it is a test file. Before we can start writing a test file u need to import the required libraries for testing. This can be done by using the following.import { Test, TestingModule } from '@nestjs/testing'; After importing, now we can define a test suite. To define a test suite we use the describe method and all the test and sub-suites will be inside it as ...]]></description>
            <content:encoded><![CDATA[<h2 id="h-unit-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Unit Test</h2><p>Unit tests in NestJs uses Jest under the hood.</p><p>Your test file should have the extension <code>fileName.spec.ts</code> the <code>spec</code> specifies that it is a test file.</p><p>Before we can start writing a test file u need to import the required libraries for testing. This can be done by using the following.</p><pre data-type="codeBlock" text="import { Test, TestingModule } from &apos;@nestjs/testing&apos;;
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title class_">Test</span>, <span class="hljs-title class_">TestingModule</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/testing'</span>;
</code></pre><p>After importing, now we can define a test suite. To define a test suite we use the <code>describe</code> method and all the test and sub-suites will be inside it as follows.</p><pre data-type="codeBlock" text="describe(&apos;Test-Suite-Name&apos;, () =&gt; {
    /** Write you test scripts you want here */
})
"><code>describe(<span class="hljs-string">'Test-Suite-Name'</span>, () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    <span class="hljs-comment">/** Write you test scripts you want here */</span>
})
</code></pre><p>before we write the test scripts we might want to deploy or compile or define some classes. This can be done by using the <code>beforeEach</code> method. The beforeEach method is run before every test and creates a new instance of the objects to be test. So every test has a new fresh testing object.</p><pre data-type="codeBlock" text="beforeEach(async () =&gt; {
    const module: TestingModule = await Test.createTestingModule({
    providers: [VerifyUserService, PrismaService],
    }).compile();
    verifyUser = module.get(VerifyUserService);
});
"><code>beforeEach(async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    const module: TestingModule <span class="hljs-operator">=</span> await Test.createTestingModule({
    providers: [VerifyUserService, PrismaService],
    }).compile();
    verifyUser <span class="hljs-operator">=</span> module.get(VerifyUserService);
});
</code></pre><p>inside the <code>beforeEach</code> function we have to define a test module in which the controller or service we want to test is imported. Here in the above example we are gonna be testing a <code>VerifyUserService</code>. The <code>PrismaService</code> is a dependency of the <code>VerifyUserService</code> so we have to add that as well to the providers array.</p><p>The <code>.compile()</code> makes sure to compile the test module with the given settings and assign it to the module variable. And then we use the <code>get</code> method on the <code>module</code> to get the <code>VerifyUserService</code> and defined it to a variable. This is a global variable and hence can be used in the tests.</p><h2 id="h-mocking-dependencies-in-services-and-controllers" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Mocking Dependencies in Services and Controllers</h2><p>In certain scenarios we might not want to fully integrate and use all the dependencies for testing just the required part. For example if we want to just test a Service or controller and not want to also have to worry about their dependencies then we can mock these dependencies.</p><p>We can mock a service as follows</p><pre data-type="codeBlock" text="beforeEach(async () =&gt; {
    const module: TestingModule = await Test.createTestingModule({
    providers: [VerifyUserService, PrismaService],
    })
        .overrideProvider(PrismaService)
        .useValue(mockPrisma)
        .compile();
    verifyUser = module.get(VerifyUserService);
});
"><code>beforeEach(async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    const module: TestingModule <span class="hljs-operator">=</span> await Test.createTestingModule({
    providers: [VerifyUserService, PrismaService],
    })
        .overrideProvider(PrismaService)
        .useValue(mockPrisma)
        .compile();
    verifyUser <span class="hljs-operator">=</span> module.get(VerifyUserService);
});
</code></pre><p>As you can see the difference we have added the <code>.overrideProvider</code> and <code>.useValue</code> method before compiling the module.</p><p><code>.overrideProvider</code> is used to specify which provider/service to modify and <code>.useValue</code> is used to specifiy a pre-defined mock object which will instead be used of the actual provider.</p><p>This Value can be defined as</p><pre data-type="codeBlock" text="const mockPrisma = {
    user: {
        findFirst: jest.fn((input) =&gt; {
            return { success:true, input: input };
        }),
    },
};
"><code>const mockPrisma <span class="hljs-operator">=</span> {
    user: {
        findFirst: jest.fn((input) <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
            <span class="hljs-keyword">return</span> { success:<span class="hljs-literal">true</span>, input: input };
        }),
    },
};
</code></pre><p>Now the above mock object defines a <code>user.findFirst</code> function. So when this function is called inside the provider we are testing this mocked function will be run instead of the actual function in provider. We use <code>jest.fn()</code> to define the mock function inside the mock object.</p><h2 id="h-testing" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Testing</h2><p>Finally to write test scripts, we need to use the <code>it</code> method to define a name for the test and the function of the test. It can be done as follows.</p><pre data-type="codeBlock" text="it(&apos;test Name&apos;, async () =&gt; {
    /** Write Tests here */
});
"><code>it(<span class="hljs-string">'test Name'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    <span class="hljs-comment">/** Write Tests here */</span>
});
</code></pre><p>To assert any condition we must use the <code>expect</code> method.</p><pre data-type="codeBlock" text="await expect(verifyUser.verifyUser(userDTO)).resolves.toEqual({
    success: true,
    user: { userId: &apos;kshdvfsd&apos;},
});
"><code>await expect(verifyUser.verifyUser(userDTO)).resolves.toEqual({
    success: <span class="hljs-literal">true</span>,
    user: { userId: <span class="hljs-string">'kshdvfsd'</span>},
});
</code></pre><p>The function we are trying to test must be inside the <code>expect</code> method. And if the function we are testing is an async function. The we can use await at the beginning of the line and <code>.resolves</code> to wait till the call resolves to complete the assertion. <code>.toEqual</code> verifies the returned object from the function call is the same as the one given here.</p><h2 id="h-run-test" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Run Test</h2><p>To run the tests in the command line use the following command</p><pre data-type="codeBlock" text="pnpm run test:dev
"><code>pnpm run test:dev
</code></pre><p>To make the tests run everytime there is a change in it, use the following</p><pre data-type="codeBlock" text="pnpm run test:watch
"><code>pnpm run test:watch
</code></pre><h2 id="h-references" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">References</h2><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=dXOfOgFFKuY">https://www.youtube.com/watch?v=dXOfOgFFKuY</a></p></li></ul>]]></content:encoded>
            <author>rustboot@newsletter.paragraph.com (rustboot.eth)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/af0f4772a93a7171199e2288b5fbe3484cc4ac6d62c38af280d9615bce26e156.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[EVM Contracts - How it manages and stores data]]></title>
            <link>https://paragraph.com/@rustboot/evm-contracts-how-it-manages-and-stores-data</link>
            <guid>WnmL2Hr5OGwEIvpDvj26</guid>
            <pubDate>Thu, 04 Apr 2024 12:50:20 GMT</pubDate>
            <description><![CDATA[What is the EVM?EVM or the Ethereum Virtual Machine is the building block of most smart contract blockchain. It is machine bytecode which all the nodes in the ethereum and other EVM block chains use to process data. It can be thought of as a set of instructions on how to compute a given data. It is an commonly agreed set of instructions everyone uses to process smart contract transactions and their input data. Given that it is such a fundamental thing in web3, it is important to understand th...]]></description>
            <content:encoded><![CDATA[<h2 id="h-what-is-the-evm" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What is the EVM?</h2><p><strong>EVM or the Ethereum Virtual Machine is the building block of most smart contract blockchain</strong>. It is machine bytecode which all the nodes in the ethereum and other EVM block chains use to process data.</p><p>It can be thought of as <strong>a set of instructions on how to compute a given data</strong>. It is an commonly agreed set of instructions everyone uses to process smart contract transactions and their input data.</p><p>Given that it is such a fundamental thing in web3, it is important to understand the inner working of the EVM. So here in this article, I&apos;ve compiled my notes on how I understand the EVM to work and to share it with the internet for others to understand and to correct me if I&apos;m wrong. This article is an attempt to share what I&apos;ve learned and what misunderstandings I might hold in this topic. Feel free to correct me or add extra points to it on the comments below.</p><p>So coming back to the topic at hand. How does contracts in the EVM manage the data given to it, and in terms of tokens(like ERC20, ERC721 etc) how does it keep track of who owns how much.</p><p>In other words, how do smart contract manage their data. To understand that, we first need to understand where at any given point in time during the processing of a transaction, a data element can be present.</p><p>There are 4 types of ways data is stored during the processing of transaction. That is</p><ol><li><p>Storage</p></li><li><p>Memory</p></li><li><p>Stack</p></li><li><p>Transient storage</p></li></ol><h2 id="h-storage" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Storage</h2><p>Storage is a place where data is stored permanently. It can be deleted or updated by the contract code. <strong>State Variables in solidity are stored in Storage</strong>.</p><p>Storage is further divided into <em>Slot</em>. Each Slot in storage can <strong>store upto a 32 bytes</strong> in it.</p><p>And the EVM stores and accesses the storage slot by using the <code>sstore</code> and <code>sload</code> opcode (opcode is the technical name for an <code>instruction</code> ).</p><h3 id="h-storage-layout" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Storage Layout</h3><p><strong>State variables</strong> of contracts are stored in storage in a compact way such that <strong>multiple values sometimes use the same storage slot</strong>. Except for dynamically-sized arrays and mappings, data is <strong>stored contiguously item after item starting with</strong> the first state variable, which is <strong>stored in slot 0</strong></p><h3 id="h-storage-layout-packing" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Storage Layout Packing</h3><p>For each <strong>state variable</strong>, a size in bytes is determined according to its type. Multiple, contiguous <strong>items that need less than 32 bytes are packed into a single storage slot</strong> if possible, according to the following rules</p><ol><li><p>The first item in a storage slot is stored lower-order aligned (i.e the first item is storage first/left)</p></li><li><p><strong>Value types</strong> use only as <strong>many bytes as are necessary</strong> to store them</p></li><li><p>If a <strong>value type does not fit the remaining part of a storage slot, it is stored in the next storage slot</strong></p></li></ol><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/854540a570ac62c3cc334cda63ca17953e5f525019e1ab009fc5ac8b577b2da4.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h2 id="h-memory" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Memory</strong></h2><p>This is the temperary data stored for the duration of a transaction call and at the end of the call it is deleted.</p><p>Memory is considerably cheaper to access and store to as it will be deleted after the transaction call. Unlike storage which is the same throughout the contract and all calls, a new instance of memory is created for each transaction call. The data stored in one instance can&apos;t be accessed by another call or vice-versa. So if a function or the contract is re-entered in the middle of a transaction, there will multiple instances of memory for each transaction call.</p><p>Memory just like storage consists of slots and each slot can hold upto 32 bytes.</p><p>The memory can be stored to and accessed by the opcodes <code>mstore</code> and <code>mload</code> respectively.</p><h2 id="h-stack" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Stack</h2><p>The Stack is the place in the EVM in which data has to placed, before you can do any kind of computation. The Stack can be thought of as the <strong>work station of the EVM</strong>. If you want to do anything, (and I mean literally anything) you have to have it in the stack.</p><p>For example, if you want to add two number, you have to push those numbers to the stack first. You want to multiple? push it to the stack first. Want to store a variable in storage or memory? push it to the stack first. Even the above mentioned <code>sload</code> and <code>mload</code> are are used to take copy the data in certain slots in storage and memory and push it to the top of the stack. And <code>mstore</code> and <code>store</code> are used to write to certain slots in memory and storage.</p><p>The stack as the name suggests should be thought of as a stack of data elements stacked on top of others. Each element can have a maximum of 32 bytes.</p><p>Its a last in, first out mechanism. Anything you push to the stack will always be placed in the top of the stack and to access the ones lower in the stack you have to remove the top ones.</p><p>I&apos;ve added a diagram from one of my notes for better visualisation.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/774fd4e40b8bb56a4e71bb736fa40f854364e6c290d37eccd199ec8d6246bbce.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>![[EVM Stack Diagram]]</p><h2 id="h-transient-storage" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Transient Storage</h2><p>Transient storage is the most recently add type of storage to the EVM. It borrows aspects from both memory and storage. Lets start with the similarities first.</p><p>Just like storage and memory, transient storage also consists of slots each of which can hold 32 bytes. And that is where the commonality for all three ends.</p><p>Transient storage is erased after every <strong>full transaction</strong>. Unlike memory which is deleted after every <strong>transaction call</strong>. Remember every transaction can have multiple internal calls, sometimes even to the same contract.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>In brief, contracts mainly use four types of data stores, Stack, Memory, Storage and Transient Storage.</p><ol><li><p>Storage- is Permanent until the contract updates or deletes it.</p></li><li><p>Memory- New instance of memory created for every transaction call. Deleted after every transaction call ends.</p></li><li><p>Transient Storage - Deleted after every transaction and is access to all transaction calls.</p></li><li><p>Stack- the place data has to be placed before you can start doing stuff with it</p></li></ol>]]></content:encoded>
            <author>rustboot@newsletter.paragraph.com (rustboot.eth)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/6a79db34ab4ea45d430dbcab1178ddf0bb06966184c4d39123c4ada026167626.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>