<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ethereum EIPs - Last Call Review</title>
    <description>All EIPs which are in the two-week "last call" status, please help review these and provide your feedback!</description>
    <link>https://eips.ethereum.org</link>
    <atom:link href="https://eips.ethereum.org/rss/last-call.xml" rel="self" type="application/rss+xml" />
    <lastBuildDate>Sat, 10 Oct 2026 23:33:34 +0000</lastBuildDate>
    
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Add chain id to mixed-case checksum address encoding</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #1191 - Add chain id to mixed-case checksum address encoding&lt;/strong&gt; is in Last Call status. It is authored by Juliano Rizzo (@juli) and was originally created 2018-03-18. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://github.com/ethereum/EIPs/issues/1121&quot;&gt;https://github.com/ethereum/EIPs/issues/1121&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;simple-summary&quot;&gt;Simple Summary&lt;/h2&gt;

&lt;p&gt;This EIP extends &lt;a href=&quot;/EIPS/eip-55&quot;&gt;EIP-55&lt;/a&gt; by optionally adding a chain id defined by &lt;a href=&quot;/EIPS/eip-155&quot;&gt;EIP-155&lt;/a&gt; to the checksum calculation.&lt;/p&gt;

&lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;/EIPS/eip-55&quot;&gt;EIP-55&lt;/a&gt; was created to prevent users from losing funds by sending them to invalid addresses. This EIP extends &lt;a href=&quot;/EIPS/eip-55&quot;&gt;EIP-55&lt;/a&gt; to protect users from losing funds by sending them to addresses that are valid but that where obtained from a client of another network.For example, if this EIP is implemented, a wallet can alert the user that is trying to send funds to an Ethereum Testnet address from an Ethereum Mainnet wallet.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;The motivation of this proposal is to provide a mechanism to allow software to distinguish addresses from different Ethereum based networks. This proposal is necessary because Ethereum addresses are hashes of public keys and do not include any metadata. By extending the &lt;a href=&quot;/EIPS/eip-55&quot;&gt;EIP-55&lt;/a&gt; checksum algorithm it is possible to achieve this objective.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;Convert the address using the same algorithm defined by &lt;a href=&quot;/EIPS/eip-55&quot;&gt;EIP-55&lt;/a&gt; but if a registered chain id is provided, add it to the input of the hash function. If the chain id passed to the function belongs to a network that opted for using this checksum variant, prefix the address with the chain id and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x&lt;/code&gt; separator before calculating the hash. Then convert the address to hexadecimal, but if the ith digit is a letter (ie. it’s one of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abcdef&lt;/code&gt;) print it in uppercase if the 4*ith bit of the calculated hash is 1 otherwise print it in lowercase.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;By means of a minimal code change on existing libraries, users are protected from losing funds by mixing addresses of different Ethereum based networks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/python3
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sha3&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keccak_256&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
   addr (str): Hexadecimal address, 40 characters long with 2 characters prefix
   chainid (int): chain id from EIP-155 &quot;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;eth_checksum_encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chainid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;adopted_eip1191&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;hash_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chainid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chainid&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adopted_eip1191&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;hash_output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keccak_256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash_input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;utf8&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hexdigest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;aggregate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aggregate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;eth_mainnet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x27b1fdb04752bbc536007a920d24acb045561c26&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x3599689E6292b81B2d85451025146515070129Bb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x42712D45473476b98452f434e72461577D686318&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x52908400098527886E0F7030069857D2E4169EE7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x6549f4939460DE12611948b3f82b88C3C8975323&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x66f9664f97F2b50F62D13eA064982f936dE76657&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x8617E340B3D01FA5F11F306F4090FD50E238070D&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x88021160C5C792225E4E5452585947470010289D&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xde709f2102306220921060314715629080e2fb77&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rsk_mainnet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x27b1FdB04752BBc536007A920D24ACB045561c26&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x3599689E6292B81B2D85451025146515070129Bb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x42712D45473476B98452f434E72461577d686318&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x52908400098527886E0F7030069857D2E4169ee7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x6549F4939460DE12611948B3F82B88C3C8975323&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x66F9664f97f2B50F62d13EA064982F936de76657&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x8617E340b3D01Fa5f11f306f4090fd50E238070D&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x88021160c5C792225E4E5452585947470010289d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xD1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xDBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xDe709F2102306220921060314715629080e2FB77&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xFb6916095cA1Df60bb79ce92cE3EA74c37c5d359&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rsk_testnet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x27B1FdB04752BbC536007a920D24acB045561C26&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x3599689e6292b81b2D85451025146515070129Bb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x42712D45473476B98452F434E72461577D686318&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x52908400098527886E0F7030069857D2e4169EE7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x6549f4939460dE12611948b3f82b88C3c8975323&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x66f9664F97F2b50f62d13eA064982F936DE76657&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x8617e340b3D01fa5F11f306F4090Fd50e238070d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0x88021160c5C792225E4E5452585947470010289d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xd1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xdbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xDE709F2102306220921060314715629080e2Fb77&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;0xFb6916095CA1dF60bb79CE92ce3Ea74C37c5D359&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;test_cases&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rsk_mainnet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rsk_testnet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eth_mainnet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chainid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cases&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_cases&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cases&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eth_checksum_encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chainid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;

&lt;h3 id=&quot;usage--table&quot;&gt;Usage  Table&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Network&lt;/th&gt;
      &lt;th&gt;Chain id&lt;/th&gt;
      &lt;th&gt;Supports this EIP&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;RSK Mainnet&lt;/td&gt;
      &lt;td&gt;30&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;RSK Testnet&lt;/td&gt;
      &lt;td&gt;31&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;implementation-table&quot;&gt;Implementation Table&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Project&lt;/th&gt;
      &lt;th&gt;EIP Usage&lt;/th&gt;
      &lt;th&gt;Implementation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;MyCrypto&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/MyCryptoHQ/MyCrypto/blob/develop/common/utils/formatters.ts#L126&quot;&gt;JavaScript&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MyEtherWallet&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/MyEtherWallet/MyEtherWallet/blob/73c4a24f8f67c655749ac990c5b62efd92a2b11a/src/helpers/addressUtils.js#L22&quot;&gt;JavaScript&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Ledger&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/LedgerHQ/ledger-app-eth/blob/master/src_common/ethUtils.c#L203&quot;&gt;C&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Trezor&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/trezor/trezor-core/blob/270bf732121d004a4cd1ab129adaccf7346ff1db/src/apps/ethereum/get_address.py#L32&quot;&gt;Python&lt;/a&gt; and &lt;a href=&quot;https://github.com/trezor/trezor-crypto/blob/4153e662b60a0d83c1be15150f18483a37e9092c/address.c#L62&quot;&gt;C&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Web3.js&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/ethereum/web3.js/blob/aaf26c8806bc9fb60cf6dcb6658104963c6c7fc7/packages/web3-utils/src/Utils.js#L140&quot;&gt;JavaScript&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;EthereumJS-util&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/ethereumjs/ethereumjs-util/pull/204/commits/cdf0b3c996b05ac5b1f758f17ea9f9ed1847c1eb&quot;&gt;JavaScript&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ENS address-encoder&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/ensdomains/address-encoder/commit/5bf53b13fa014646ea28c9e5f937361dc9b40590&quot;&gt;TypeScript&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;


      </description>
        <pubDate>Sun, 18 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-1191</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-1191</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Atomic Swap-based American Call Option Contract Standard</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #2266 - Atomic Swap-based American Call Option Contract Standard&lt;/strong&gt; is in Last Call status. It is authored by Runchao Han &lt;runchao.han@monash.edu&gt;, Haoyu Lin &lt;chris.haoyul@gmail.com&gt;, Jiangshan Yu &lt;jiangshan.yu@monash.edu&gt; and was originally created 2019-08-17. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://github.com/ethereum/EIPs/issues/2266&quot;&gt;https://github.com/ethereum/EIPs/issues/2266&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;simple-summary&quot;&gt;Simple Summary&lt;/h2&gt;

&lt;p&gt;A standard for token contracts providing Atomic Swap-based American Call Option functionalities.&lt;/p&gt;

&lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This standard provides functionality to make Atomic Swap-based American Call Option payment. The Atomic Swap protocol based on Hashed Time-Locked Contract (HTLC) &lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; has optionality &lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, and such optionality can be utilised to construct American Call Options without trusted third party. This standard defines the common way of implementing this protocol. In particular, this EIP defines technical terms, provides interfaces, and gives reference implementations of this protocol.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Atomic Swap allows users to atomically exchange their tokens without trusted third parties while the HTLC is commonly used for the implementation. However, the HTLC-based Atomic Swap has optionality. More specifically, the swap initiator can choose to proceed or abort the swap for several hours, which gives him time for speculating according to the exchange rate. A discussion&lt;sup id=&quot;fnref:2:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; shows that the HTLC-based Atomic Swap is equivalent to an American Call Option in finance. On the other hand,thanks to such optionality, the HTLC-based Atomic Swap can be utilised to construct American Call Options without trusted third party. A paper&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; proposes a secure Atomic-Swap-based American Call Option protocol on smart contracts. This protocol not only eliminates the arbitrage opportunity but also prevents any party from locking the other party’s money maliciously. This EIP aims at providing the standard of implementing this protocol in existing token standards.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The Atomic Swap-based American Call Option smart contract should follow the syntax and semantics of Ethereum smart contracts.&lt;/p&gt;

&lt;h3 id=&quot;definitions&quot;&gt;Definitions&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiator&lt;/code&gt;: the party who publishes the advertisement of the swap.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;participant&lt;/code&gt;: the party who agrees on the advertisement and participates in the swap with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiator&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asset&lt;/code&gt;: the amount of token(s) to be exchanged.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;premium&lt;/code&gt;: the amount of token(s) that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiator&lt;/code&gt; pays to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;participant&lt;/code&gt; as the premium.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redeem&lt;/code&gt;: the action to claim the token from the other party.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;refund&lt;/code&gt;: the action to claim the token from the party herself/himself, because of timelock expiration.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secrect&lt;/code&gt;: a random string chosen by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiator&lt;/code&gt; as the preimage of a hash.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secrectHash&lt;/code&gt;: a string equals to the hash of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secrect&lt;/code&gt;, used for constructing HTLCs.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;timelock&lt;/code&gt;: a timestamp representing the timelimit, before when the asset can be redeemed, and otherwise can only be refunded.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;storage-variables&quot;&gt;Storage Variables&lt;/h3&gt;

&lt;h4 id=&quot;swap&quot;&gt;swap&lt;/h4&gt;

&lt;p&gt;This mapping stores the metadata of the swap contracts, including the parties and tokens involved. Each contract uses different &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secretHash&lt;/code&gt;, and is distinguished by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secretHash&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Swap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;swap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;initiatorasset&quot;&gt;initiatorAsset&lt;/h4&gt;

&lt;p&gt;This mapping stores the detail of the asset initiators want to sell, including the amount, the timelock and the state. It is associated with the swap contract with the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secretHash&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InitiatorAsset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatorAsset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;participantasset&quot;&gt;participantAsset&lt;/h4&gt;

&lt;p&gt;This mapping stores the details of the asset participants want to sell, including the amount, the timelock and the state. It is associated with the swap contract with the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secretHash&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParticipantAsset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participantAsset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;premiumasset&quot;&gt;premiumAsset&lt;/h4&gt;

&lt;p&gt;This mapping stores the details of the premium initiators attach in the swap contract, including the amount, the timelock and the state. It is associated with the swap contract with the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secretHash&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Premium&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premium&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;methods&quot;&gt;Methods&lt;/h3&gt;

&lt;h4 id=&quot;setup&quot;&gt;setup&lt;/h4&gt;

&lt;p&gt;This function sets up the swap contract, including the both parties involved, the tokens to exchanged, and so on.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatorAssetAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participantAssetAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premiumAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;initiate&quot;&gt;initiate&lt;/h4&gt;

&lt;p&gt;The initiator invokes this function to fill and lock the token she/he wants to sell and join the contract.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetRefundTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;fillpremium&quot;&gt;fillPremium&lt;/h4&gt;

&lt;p&gt;The initiator invokes this function to fill and lock the premium.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fillPremium&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premiumRefundTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;participate&quot;&gt;participate&lt;/h4&gt;

&lt;p&gt;The participant invokes this function to fill and lock the token she/he wants to sell and join the contract.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetRefundTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;redeemasset&quot;&gt;redeemAsset&lt;/h4&gt;

&lt;p&gt;One of the parties invokes this function to get the token from the other party, by providing the preimage of the hash lock &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secret&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redeemAsset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;refundasset&quot;&gt;refundAsset&lt;/h4&gt;

&lt;p&gt;One of the parties invokes this function to get the token back after the timelock expires.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refundAsset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;redeempremium&quot;&gt;redeemPremium&lt;/h4&gt;

&lt;p&gt;The participant invokes this function to get the premium. This can be invoked only if the participant has already invoked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;participate&lt;/code&gt; and the participant’s token is redeemed or refunded.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redeemPremium&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;refundpremium&quot;&gt;refundPremium&lt;/h4&gt;

&lt;p&gt;The initiator invokes this function to get the premium back after the timelock expires.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refundPremium&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;events&quot;&gt;Events&lt;/h3&gt;

&lt;h4 id=&quot;setup-1&quot;&gt;SetUp&lt;/h4&gt;

&lt;p&gt;This event indicates that one party has set up the contract using the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup()&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SetUp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatorAssetAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participantAssetAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premiumAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;initiated&quot;&gt;Initiated&lt;/h4&gt;

&lt;p&gt;This event indicates that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiator&lt;/code&gt; has filled and locked the token to be exchanged using the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiate()&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Initiated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiateTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatorAssetToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatorAssetAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatorAssetRefundTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;participated&quot;&gt;Participated&lt;/h4&gt;

&lt;p&gt;This event indicates that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;participant&lt;/code&gt; has filled and locked the token to be exchanged using the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;participate()&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Participated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participateTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participantAssetToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participantAssetAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participantAssetRefundTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;premiumfilled&quot;&gt;PremiumFilled&lt;/h4&gt;

&lt;p&gt;This event indicates that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiator&lt;/code&gt; has filled and locked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;premium&lt;/code&gt; using the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fillPremium()&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PremiumFilled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fillPremiumTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;participant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premiumToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premiumAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premiumRefundTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;initiatorassetredeemedparticipantassetredeemed&quot;&gt;InitiatorAssetRedeemed/ParticipantAssetRedeemed&lt;/h4&gt;

&lt;p&gt;These two events indicate that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asset&lt;/code&gt; has been redeemed by the other party before the timelock by providing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secret&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InitiatorAssetRedeemed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redeemTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redeemer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParticipantAssetRedeemed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redeemTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redeemer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;initiatorassetrefundedparticipantassetrefunded&quot;&gt;InitiatorAssetRefunded/ParticipantAssetRefunded&lt;/h4&gt;

&lt;p&gt;These two events indicate that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asset&lt;/code&gt; has been refunded by the original owner after the timelock expires.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InitiatorAssetRefunded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refundTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refunder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParticipantAssetRefunded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refundTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refunder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;premiumredeemed&quot;&gt;PremiumRedeemed&lt;/h4&gt;

&lt;p&gt;This event indicates that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;premium&lt;/code&gt; has been redeemed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;participant&lt;/code&gt;. This implies that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asset&lt;/code&gt; is either redeemed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiator&lt;/code&gt; if it can provide the preimage of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secrectHash&lt;/code&gt; before  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asset&lt;/code&gt; timelock expires; or refunded by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;participant&lt;/code&gt; if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asset&lt;/code&gt; timelock expires.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PremiumRedeemed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redeemTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redeemer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;premiumrefunded&quot;&gt;PremiumRefunded&lt;/h4&gt;

&lt;p&gt;This event indicates that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;premium&lt;/code&gt; has been refunded back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiator&lt;/code&gt;, because of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;participant&lt;/code&gt; doesn’t participate at all, by the time of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;premium&lt;/code&gt; timelock expires.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PremiumRefunded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refundTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refunder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;To achieve the atomicity, HTLC is used.&lt;/li&gt;
  &lt;li&gt;The participant should decide whether to participate after the initiator locks the token and sets up the timelock.&lt;/li&gt;
  &lt;li&gt;The initiator should decide whether to proceed the swap (redeem the tokens from the participant and reveal the preimage of the hash lock), after the participant locks the tokens and sets up the time locks.&lt;/li&gt;
  &lt;li&gt;Premium is redeemable for the participant only if the participant participates in the swap and redeems the initiator’s token before premium’s timelock expires.&lt;/li&gt;
  &lt;li&gt;Premium is refundable for the initiator only if the initiator initiates but the participant does not participate in the swap at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiateTimestamp&lt;/code&gt; should cover the whole swap process.&lt;/li&gt;
  &lt;li&gt;The participant should never participate before the premium has been deposited.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This proposal is fully backward compatible. Functionalities of existing standards will not be affected by this proposal, as it only provides additional features to them.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;Please visit &lt;a href=&quot;/assets/eip-2266/Example.sol&quot;&gt;here&lt;/a&gt; to find our example implementation.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts&quot;&gt;Hash Time Locked Contracts&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://lists.linuxfoundation.org/pipermail/lightning-dev/2019-January/001798.html&quot;&gt;An Argument For Single-Asset Lightning Network&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:2:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://eprint.iacr.org/2019/896&quot;&gt;On the optionality and fairness of Atomic Swaps&lt;/a&gt; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

      </description>
        <pubDate>Sat, 17 Aug 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-2266</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-2266</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Resource-based intrinsic transaction gas</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #2780 - Resource-based intrinsic transaction gas&lt;/strong&gt; is in Last Call status. It is authored by Matt Garnett (@lightclient), Uri Klarman (@uriklarman), Ben Adams (@benaadams), Maria Inês Silva (@misilva73), Anders Elowsson (@anderselowsson), Anthony Sassano (@sassal), Dragan Rakita (@rakita) and was originally created 2020-07-11. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-2780-reduce-intrinsic-cost-of-transactions/4413&quot;&gt;https://ethereum-magicians.org/t/eip-2780-reduce-intrinsic-cost-of-transactions/4413&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP decomposes the flat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; intrinsic transaction cost into explicit primitives, each priced to match the resources a transaction actually consumes. A plain ETH transfer to an existing account remains at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; execution gas, and contract-creation transactions cost the same whether or not they carry value. Transactions that create new accounts or interact with &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; pay the additional runtime costs they incur.&lt;/p&gt;

&lt;p&gt;In addition, the new primitives are split into intrinsic gas and runtime gas. &lt;strong&gt;Intrinsic gas&lt;/strong&gt; is the state-independent cost of including the transaction in a block and is the sole input to the transaction-validity check. &lt;strong&gt;Runtime gas&lt;/strong&gt; covers the state-dependent charges, such as new account creation and delegation resolution. Runtime gas is charged before the first frame is entered and is metered in the same way as gas inside the frame. Running out of runtime gas does not invalidate the transaction. Instead, the transaction is included, execution is skipped, and the pre-execution state changes are reverted.&lt;/p&gt;

&lt;p&gt;This EIP does not change calldata or access-list metering.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;The flat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; intrinsic cost charges every transaction the same amount regardless of what it does. A zero-value transaction to an existing account and a value transfer that creates a new account both pay &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt;, even though the latter touches an extra account, writes an extra balance, emits a log, and permanently grows the state. The single constant both over-prices the simplest paths and under-prices the ones that consume real, lasting resources.&lt;/p&gt;

&lt;p&gt;This EIP replaces the constant with a decomposition into named primitives, each priced to the resource it represents. The goal is to make every transaction’s cost reflect its actual work:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Accuracy.&lt;/strong&gt; Signature recovery, account accesses, account writes, value transfers, and state creation are billed separately, so cost tracks usage.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;State growth is internalized.&lt;/strong&gt; A value transfer that creates an account, like a contract-creation transaction, pays &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; in state gas. This aligns top-level value transfers with internal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt;-based account creation, which already pays for the new leaf, and prices the durable state cost the flat base ignored.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Composability.&lt;/strong&gt; Pricing intrinsic cost as a sum of the same primitives used elsewhere in the gas schedule lets future repricings (e.g. of cold-account access in &lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;, or of state bytes in &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;) flow through automatically, without re-deriving a bespoke constant.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No worst-case reservation.&lt;/strong&gt; State-dependent costs, such as new account creation and delegation resolution, are charged at runtime only when a transaction incurs them, rather than reserved up front. Intrinsic gas covers only inclusion and remains the sole validity input, so a transaction that funds inclusion but not a runtime charge is included, charged for the gas consumed, and reverted, exactly like an out-of-gas halt inside a call frame.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;parameters&quot;&gt;Parameters&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Name&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Value&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Definition&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12,000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Sender cost: ECDSA recovery, the sender’s account access, the sender’s account write and inclusion in block&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;6,000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Recipient balance write and &lt;a href=&quot;/EIPS/eip-7708&quot;&gt;EIP-7708&lt;/a&gt; transfer log performed by a value transfer&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The remaining values are defined in other EIPs and referenced here:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Name&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Value&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Source&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Definition&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;3,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Cold account touch&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;100&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Warm account touch&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;9,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;First write to an account leaf&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Contract-deployment account access and write&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;7,816&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Per-authorization base: calldata, ECDSA recovery, cold authority access, and warm writes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;183,600&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;State gas for one new account leaf&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_AUTH_BASE × CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;35,190&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;State gas for one 23-byte delegation indicator&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The two state-gas products change whenever &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; changes. Execution-gas and state-gas semantics are defined by &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;intrinsic-gas-costs&quot;&gt;Intrinsic gas costs&lt;/h3&gt;

&lt;p&gt;A transaction’s intrinsic base cost is decomposed into the following explicit primitives:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.sender&lt;/code&gt; is charged &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; in execution gas, accounting for one ECDSA recovery, the sender’s account access and write, and the inclusion of the transaction’s bytes in the block.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.to&lt;/code&gt; is charged based on its type:
    &lt;ul&gt;
      &lt;li&gt;if self-transfer (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.sender == tx.to&lt;/code&gt;), there are no charges;&lt;/li&gt;
      &lt;li&gt;if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt; (contract-creation transaction), charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt; in execution gas; the new-account state charge depends on whether the deployment target exists and is charged at runtime;&lt;/li&gt;
      &lt;li&gt;otherwise, charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; in execution gas (covering the recipient touch, charged at the cold rate unconditionally).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.value&lt;/code&gt; is charged based on its value:
    &lt;ul&gt;
      &lt;li&gt;if zero, there are no charges;&lt;/li&gt;
      &lt;li&gt;if non-zero and self-transfer, there are no charges;&lt;/li&gt;
      &lt;li&gt;if non-zero and contract creation, there are no charges; the recipient balance write is already covered by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt;;&lt;/li&gt;
      &lt;li&gt;otherwise, charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt; in execution gas.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;each &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorization is charged &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt; in execution gas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The recipient touch and the authority access (inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt;) are charged at the cold rate every time, even if the account would be warm (for example, via an access list), keeping intrinsic gas computable without any state read.&lt;/p&gt;

&lt;p&gt;These charges replace the legacy contract-creation transaction charges and EIP-7702’s flat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_EMPTY_ACCOUNT_COST × authorization_list_length&lt;/code&gt; intrinsic charge.&lt;/p&gt;

&lt;p&gt;Calldata and access-list metering remain unchanged.&lt;/p&gt;

&lt;h3 id=&quot;runtime-gas-costs&quot;&gt;Runtime gas costs&lt;/h3&gt;

&lt;p&gt;Once the transaction passes the intrinsic gas check, the state-dependent gas costs (i.e., runtime costs) are applied. The runtime charges happen in a distinct window — the pre-execution phase — after the transaction is already deemed valid but before the first EVM frame is entered. This phase includes the following actions, in order:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The available gas is split into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt;, and all the gas accounting counters are initialized, per &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorizations are processed;&lt;/li&gt;
  &lt;li&gt;The recipient account is added to the &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;’s Block-Level Access List (its access was already charged at the cold rate at the intrinsic phase, and it is warm from transaction start);&lt;/li&gt;
  &lt;li&gt;The remaining account creation and access costs are applied.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Like every charge in this EIP, each runtime charge is split into execution gas and state gas per &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;: account accesses and writes are execution gas, while durable state growth (new account leaves and net-new delegation bytes) is state gas. This mirrors how a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; frame is metered: accesses, account creation, and writes are charged as state is touched, not up front.&lt;/p&gt;

&lt;p&gt;Running out of gas during these runtime charges does &lt;strong&gt;not&lt;/strong&gt; invalidate the transaction. Validity is decided solely by the intrinsic gas check.&lt;/p&gt;

&lt;p&gt;If the transaction goes out-of-gas in this pre-execution phase, the sender pays for all gas consumed, and all pre-execution state changes are reverted, including any &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; delegations. The included transaction still increments the sender’s nonce and pays its gas fees. By contrast, if the transaction goes out-of-gas after entering the first EVM frame, the delegations applied during the pre-execution phase stay in place, per &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt;; the state gas that paid for them — each authority’s account-creation and delegation-indicator bytes — therefore stays consumed, since that state persists beyond the frame. Runtime state charges whose state is instead rolled back with the frame (for example, a contract-creation transaction’s new-account charge; see below) are refilled in LIFO order per &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;, and execution-gas runtime charges (such as a delegation-target access) remain consumed.&lt;/p&gt;

&lt;p&gt;If a contract-creation transaction’s initcode reverts, the transaction remains valid and any state gas charged at runtime is refilled in last-in, first-out (LIFO) order, per &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;: the portion the charge drew from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; is credited back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;, and only the remainder returns to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On an exceptional halt, the same LIFO refill applies. A plain value transfer to a new account executes no code and so cannot revert. Its new-account state charge is therefore never rolled back this way. The exception is a transfer to an empty precompile, which does execute and can fail, though on mainnet all precompiles are already pre-funded.&lt;/p&gt;

&lt;h4 id=&quot;eip-7702-authorization-processing&quot;&gt;&lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorization processing&lt;/h4&gt;

&lt;p&gt;While processing each valid authorization, the following charges are applied &lt;strong&gt;at most once per authority&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;if the authority account does not already exist, charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; in state gas for the new account leaf;&lt;/li&gt;
  &lt;li&gt;if this is the first write to the authority within the transaction, charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; in execution gas; the charge is skipped when the write is already paid for, namely when the authority:
    &lt;ul&gt;
      &lt;li&gt;is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.sender&lt;/code&gt;, covered by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt;;&lt;/li&gt;
      &lt;li&gt;was written by a preceding valid authorization;&lt;/li&gt;
      &lt;li&gt;is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.to&lt;/code&gt; of a value-bearing transaction, covered by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt;;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;if the authorization sets a non-zero delegation target, the authority had no delegation indicator at transaction start, and no earlier authorization set one for that authority in this transaction, charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_AUTH_BASE × CPSB&lt;/code&gt; in state gas. Clearing an indicator does not refund this charge or make a later set chargeable again. An indicator present at transaction start can be cleared and re-set without paying this charge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Authorization validation and warming retain the ordering in &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt;: check the chain ID and nonce bound, recover the authority, add it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accessed_addresses&lt;/code&gt;, and then check its code and current nonce. An authorization skipped because of the latter checks still warms the recovered authority; one rejected before recovery does not. The state-dependent charges above apply only after validation succeeds, before applying the authorization.&lt;/p&gt;

&lt;h4 id=&quot;account-creation-and-access-charges&quot;&gt;Account creation and access charges&lt;/h4&gt;

&lt;p&gt;If the transaction is not a contract creation, then the following charges are applied:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;if the recipient is non-existent and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.value &amp;gt; 0&lt;/code&gt;, charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; in state gas (never applies to a self-transfer, whose recipient is the already-existing sender);&lt;/li&gt;
  &lt;li&gt;if the recipient is an &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; delegated account, additionally charge the delegation-target access in execution gas: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; if cold, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; if warm.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a contract-creation transaction, if the deployment address does not already exist, per the existence rule of &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;, charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; in state gas.&lt;/p&gt;

&lt;h3 id=&quot;transaction-reference-cases&quot;&gt;Transaction reference cases&lt;/h3&gt;

&lt;p&gt;Costs are split between the intrinsic phase and the runtime phase, each in execution gas and state gas, per &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;. “execution” denotes contract execution charged at the standard schedule; it, and every runtime charge, is drawn from the gas passed into the first frame, so that frame is entered with the gas remaining after the runtime execution and state charges. The recipient touch is charged at the cold rate at the intrinsic phase; the only runtime account access is the delegation-target load, shown at the cold rate — a target warmed beforehand pays &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;. Create rows assume the deployment target does not already exist; a pre-existing target pays no new-account state charge. A plain ETH transfer to an existing EOA remains at the legacy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; execution gas; the other rows show the decomposition for each transaction shape.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Case&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Intrinsic (execution / state)&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Runtime (execution / state)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Total (execution / state)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ETH transfer to self&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0 / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12,000 / 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;No-transfer to EOA / empty account&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0 / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;15,000 / 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;No-transfer to contract&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;execution / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;15,000 + execution / 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ETH transfer to existing EOA&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS + TX_VALUE_COST&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0 / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;21,000 / 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ETH transfer to contract&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS + TX_VALUE_COST&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;execution / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;21,000 + execution / 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;No-transfer to 7702 delegated&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; + execution / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;18,000 + execution / 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ETH transfer to 7702 delegated&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS + TX_VALUE_COST&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; + execution / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;24,000 + execution / 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ETH transfer to self, sender 7702 delegated&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; + execution / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;15,000 + execution / 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ETH transfer creating new account&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS + TX_VALUE_COST&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0 / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;21,000 / 183,600&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Create transaction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.value&lt;/code&gt; = 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + CREATE_ACCESS&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0 / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;24,000 / 183,600&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Create transaction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.value&lt;/code&gt; &amp;gt; 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + CREATE_ACCESS&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0 / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;24,000 / 183,600&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Create transaction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.value&lt;/code&gt; &amp;gt; 0, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;created_address.balance&lt;/code&gt; &amp;gt; 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + CREATE_ACCESS&lt;/code&gt; / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0 / 0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;24,000 / 0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;interactions-with-other-eips&quot;&gt;Interactions with other EIPs&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt; (warm/cold accounting).&lt;/strong&gt; The sender access folded into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt;, the recipient’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;, and the authority access inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt; are all charged at the intrinsic phase at fixed cold rates, independent of the account’s warm/cold state — an access-list entry for the recipient or an authority does not discount them. The sender, the recipient, and each processed authority are added to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accessed_addresses&lt;/code&gt;, so subsequent execution-level touches are warm. The only runtime account access is the delegation-target load, which follows the standard EIP-2929 warm/cold model: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; if cold, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; if warm. The same model governs all execution-level account touches, including internal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt;s.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-2930&quot;&gt;EIP-2930&lt;/a&gt; (access lists).&lt;/strong&gt; Access lists keep their existing per-entry charges and warming semantics for execution-level touches. Listing the recipient or an authority does not reduce the intrinsic cold-rate charges; it only pre-warms the address for execution.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt; (calldata floor).&lt;/strong&gt; EIP-7623 floors a transaction’s cost at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000 + TOTAL_COST_FLOOR_PER_TOKEN × tokens_in_calldata&lt;/code&gt;, where the flat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; is the intrinsic base this EIP decomposes. With this EIP active, that base term is replaced by the transaction’s decomposed base — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; plus the applicable recipient and value primitives (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt; for a value transfer to a different account, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt; for contract creation). Per-authorization charges and initcode word charges are excluded from this base, so the floor and its validity check rest on the same per-transaction base as the rest of intrinsic gas rather than a stale constant. Like the floor, this base is state-independent, so the state-dependent runtime charges (the new-account state-gas charge and the delegation-target access) do not enter it. The calldata schedule itself is unchanged; only the base the floor sits on moves.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; (set EOA code).&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; is unchanged when the sender is delegated or an authorization changes its delegation. An authorization supplies a delegation target address, not the target’s code. Computing the intrinsic charge does not require loading that code; resolving a delegation for execution does. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.to&lt;/code&gt; is a delegated account, resolving the delegation loads the target’s code, charged &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; on first touch or warm thereafter, following the standard EIP-2929 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accessed_addresses&lt;/code&gt; model. Setting a delegation (writing the 23-byte pointer) is distinct from resolving one (reading the target’s code); the resolution charge is genuine work and is not prepaid by the authorization. Authorization cost itself is decomposed: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt; — which already includes the authority’s cold access — is charged per authorization at the intrinsic phase, while the state-dependent charges (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; for a non-existent authority, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; for the first write to the authority within the transaction, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_AUTH_BASE × CPSB&lt;/code&gt; for net-new delegation bytes) are charged at runtime during authorization processing, replacing the worst-case &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_EMPTY_ACCOUNT_COST&lt;/code&gt; intrinsic charge and refund.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-7708&quot;&gt;EIP-7708&lt;/a&gt; (ETH transfers emit a log).&lt;/strong&gt; Every non-zero-value transfer to a different account emits a transfer log; its cost is folded into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt; alongside the recipient balance write rather than priced as a separate primitive.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; (block-level access lists).&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.sender&lt;/code&gt; is accessed at the intrinsic phase and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.to&lt;/code&gt; at the runtime phase, so both are included in the block-level access list even when the transaction reverts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;intrinsic-versus-runtime-gas&quot;&gt;Intrinsic versus runtime gas&lt;/h3&gt;

&lt;p&gt;The split follows a single line: can the charge be computed without reading state? Signature recovery, the sender’s access and write, the transaction’s block bytes, the value charges, and the per-authorization base are all fixed by the transaction’s fields alone, so they are intrinsic and decide validity. The recipient touch and the authority access are also intrinsic, charged unconditionally at the cold rate: a top-level account is loaded from cold state once per transaction, and pricing that load at a fixed cold rate — rather than discounting the rare case where an access list pre-warmed it — keeps the charge state-independent without underpricing the work. The state-touching remainder is runtime, billed as each account is actually loaded: whether the recipient, an authority, or a deployment target exists, and whether a delegation must be resolved.&lt;/p&gt;

&lt;p&gt;Charging the runtime part as the first frame is entered makes the top-level transaction behave like an ordinary &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt;: a frame is metered against the gas handed to it, and exhausting that gas halts the frame without unwinding the caller’s decision to make the call. Here the “caller” is block inclusion, and the intrinsic check is its decision; a runtime out-of-gas therefore cannot retract validity. Keeping validity on a state-independent quantity is also what lets a block builder decide inclusion without executing the transaction, and lets later EIPs price new state-dependent work at runtime without ever touching the validity boundary.&lt;/p&gt;

&lt;h3 id=&quot;pricing-only-the-work-each-transaction-does&quot;&gt;Pricing only the work each transaction does&lt;/h3&gt;

&lt;p&gt;The decomposition charges each primitive once, where the resource is consumed: signature recovery and the sender’s access and write in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt;; the recipient touch in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;; the recipient balance write and transfer log in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt;; and durable state creation in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt;. A zero-value transaction pays only for the touches it makes, while a value transfer that creates an account pays for the new leaf it adds. This removes the cross-subsidy in the flat base, where simple transactions overpaid and state-creating ones underpaid.&lt;/p&gt;

&lt;p&gt;The new-account state charge does not apply to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt;: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt; opcode base already prices internal account creation, and top-level contract-creation transactions pay &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt; intrinsically plus the same state-gas charge at runtime when the deployment target does not already exist. Charging the state-growth cost on top-level value transfers that create accounts aligns them with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt;-based creation path, which has always paid for the new leaf.&lt;/p&gt;

&lt;h3 id=&quot;deriving-the-decomposition-from-measured-client-run-times&quot;&gt;Deriving the decomposition from measured client run times&lt;/h3&gt;

&lt;p&gt;The values of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt; are not set by intuition; they are derived from measured client execution times, using the same approach as &lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The derivation uses the EELS &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_ether_transfers_onchain_receivers&lt;/code&gt; benchmark, executed across all major execution-layer clients (Besu, Erigon, Geth, Nethermind, Reth). The benchmark fills blocks with ether transfers to four kinds of receiver, each exercising a different work path:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;transfers to a contract with shared code, where the code lookup is cached across transactions;&lt;/li&gt;
  &lt;li&gt;transfers to a contract with unique 24 KiB code, forcing a fresh code read and JUMPDEST analysis on every transaction (the heaviest path);&lt;/li&gt;
  &lt;li&gt;transfers to an existing EOA;&lt;/li&gt;
  &lt;li&gt;transfers to a non-existent EOA, where the client must create a new account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(client, receiver)&lt;/code&gt; pair, a non-negative least-squares model fits measured block runtime as a linear function of the number of transfers and the number of value-bearing transfers. The two fitted coefficients are the per-transfer base runtime and the additional runtime of moving value. Each coefficient is converted to gas at a fixed throughput anchor of 100 Mgas/s (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas = ceil(100,000 × runtime_ms)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For any candidate target, the analysis surfaces each client’s worst case across receiver types, separating clients that already meet the target from those that must optimize to reach it. The proposed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt; are set as such targets: they align intrinsic cost with the resource usage of well-optimized clients while leaving slower clients a defined optimization goal.&lt;/p&gt;

&lt;p&gt;The two empirical coefficients map onto the decomposition as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the per-transfer base runtime covers signature recovery, the sender’s access and write, and the recipient touch → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;the value increment covers the recipient balance write and the transfer log → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; is taken directly from &lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;, since the recipient touch is the same cold-account access priced there. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_VALUE_COST&lt;/code&gt; are the residual parameters this EIP introduces.&lt;/p&gt;

&lt;p&gt;As in &lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;, these numbers are provisional. At the 100 Mgas/s anchor some clients are currently slower than the target on the heaviest paths and must optimize to meet it; the values will be refined as client optimizations land and the benchmarks mature.&lt;/p&gt;

&lt;h3 id=&quot;not-metering-the-transaction-envelope-as-calldata&quot;&gt;Not metering the transaction envelope as calldata&lt;/h3&gt;

&lt;p&gt;Only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.data&lt;/code&gt; bytes are metered at the calldata schedule; the envelope RLP (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas*&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt;) is not. Pricing full-transaction bytes would make intrinsic gas depend on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_limit&lt;/code&gt; and variable-length signature elements — creating a fixed-point estimation problem, since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_limit&lt;/code&gt; would depend on the signature, which itself encodes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_limit&lt;/code&gt; — and would couple the fee to one serialization, weakening &lt;a href=&quot;/EIPS/eip-2718&quot;&gt;EIP-2718&lt;/a&gt; type neutrality and future encodings. Treating calldata as opaque bytes avoids both issues. A plain ETH transfer carries empty &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.data&lt;/code&gt; and so pays zero calldata gas regardless.&lt;/p&gt;

&lt;h3 id=&quot;self-transfers&quot;&gt;Self-transfers&lt;/h3&gt;

&lt;p&gt;A self-transfer (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.sender == tx.to&lt;/code&gt;) charges neither the recipient touch nor the value cost: the account is already accessed and written as the sender, and EIP-7708 emits no transfer log when sender and recipient coincide. Only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; applies to the intrinsic base. If the sender is delegated, the delegation-target access and any delegated execution are still charged at runtime.&lt;/p&gt;

&lt;h3 id=&quot;decomposing-authorization-cost&quot;&gt;Decomposing authorization cost&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; charges &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_EMPTY_ACCOUNT_COST&lt;/code&gt; per authorization at the intrinsic phase and refunds it when the authority already exists, over-reserving gas the transaction may never use. Splitting the cost removes the over-charge: only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt; — the calldata, signature recovery, cold authority access, and warm writes every authorization performs — is knowable without state access and stays intrinsic. The new-account leaf, the first-write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt;, and the delegation-indicator bytes depend on state and are charged at runtime during authorization processing, billed only for the authorities that incur them.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP is &lt;strong&gt;not&lt;/strong&gt; backward compatible. It is a consensus gas repricing that must be activated at a network upgrade. Wallets, RPCs, gas estimators, and any logic that assumes a flat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; intrinsic base must update, particularly to account for the state-gas charge on transactions that create new accounts.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Costs are given as intrinsic + runtime, by case. These examples omit calldata, access-list, and initcode word charges and, except in case 8, authorization charges; executed code is charged separately. Delegation-target accesses shown at the cold rate cost &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; instead when the target is already warm:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Self-transfer (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from == to&lt;/code&gt;): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12,000&lt;/code&gt; intrinsic, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; runtime. If the sender is 7702-delegated, the delegation-target access is additionally charged at runtime, per case 5.&lt;/li&gt;
  &lt;li&gt;Zero-value transaction to a distinct existing or empty EOA: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;15,000&lt;/code&gt; intrinsic (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS&lt;/code&gt;), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; runtime, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; state. A contract recipient additionally pays for execution; a delegated recipient also pays for the delegation-target access. A self-target has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12,000&lt;/code&gt; intrinsic base, with delegated execution charged as in case 1.&lt;/li&gt;
  &lt;li&gt;Value transfer to an existing EOA: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; intrinsic, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; runtime, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; state.&lt;/li&gt;
  &lt;li&gt;Value transfer creating a new account (recipient non-existent): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; intrinsic execution; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;183,600&lt;/code&gt; runtime state.&lt;/li&gt;
  &lt;li&gt;Value transfer to a 7702-delegated account: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; intrinsic + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; runtime = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;24,000&lt;/code&gt; execution gas plus contract execution.&lt;/li&gt;
  &lt;li&gt;Contract-creation transaction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value = 0&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;24,000&lt;/code&gt; intrinsic execution; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;183,600&lt;/code&gt; runtime state if the deployment target did not exist, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; otherwise.&lt;/li&gt;
  &lt;li&gt;Contract-creation transaction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value &amp;gt; 0&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;24,000&lt;/code&gt; intrinsic execution (identical to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value = 0&lt;/code&gt; case, since the recipient balance write is covered by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt;); &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;183,600&lt;/code&gt; runtime state if the deployment target did not exist, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; otherwise.&lt;/li&gt;
  &lt;li&gt;EIP-7702 transaction: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST&lt;/code&gt; is unchanged even when the sender assumes code. Each authorization is charged &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt; (which already covers the cold authority access) at the intrinsic phase; at runtime, a non-existent authority additionally pays &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; state, the first write to the authority within the transaction pays &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; execution, and net-new delegation bytes add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_AUTH_BASE × CPSB&lt;/code&gt; state — replacing the flat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_EMPTY_ACCOUNT_COST&lt;/code&gt; intrinsic charge and refund.&lt;/li&gt;
  &lt;li&gt;Contract-creation transaction whose initcode reverts (value-bearing or not): the transaction remains valid; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;183,600&lt;/code&gt; new-account state-gas charge is refilled in LIFO order per &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt; — credited to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; up to the portion the charge drew from it, with the remainder returning to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Transaction whose gas covers intrinsic cost but not a runtime charge — e.g. a value transfer to a non-existent recipient or a contract creation to a non-existent target lacking gas for the new-account state charge, or a transfer to a delegated account lacking gas for the delegation-target access: the transaction is valid and included, halts out-of-gas, and all runtime state changes — including any applied EIP-7702 delegations — are reverted; it is &lt;strong&gt;not&lt;/strong&gt; invalidated.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Blocks of pure ETH transfers should be tested across all EL clients (e.g. on Perfnet) to confirm the pricing matches measured run times at the chosen throughput anchor.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;The decomposed charges, intrinsic plus runtime, sum to at least the legacy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt; for any transaction that moves value to a distinct, cold account, and add state gas for transactions that grow the state. No path is cheaper than under the flat base in a way that increases per-block resource consumption; the change reallocates cost to match resources and prices state growth that was previously not priced.&lt;/p&gt;

&lt;p&gt;Moving the state-dependent charges to runtime lowers the validity threshold (a simple call is valid at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_BASE_COST + COLD_ACCOUNT_ACCESS&lt;/code&gt; rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21,000&lt;/code&gt;), but does not enable underpriced work. A transaction that passes the intrinsic check yet runs out of runtime gas is still included and the sender still pays for every gas unit consumed, with all state changes reverted — exactly the cost profile of an out-of-gas inside a call frame. The runtime mechanism thus charges the same resources as before; it only relocates where, in the lifecycle, the gas is metered.&lt;/p&gt;

&lt;p&gt;The semantics of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; are unchanged. Per &lt;a href=&quot;/EIPS/eip-6780&quot;&gt;EIP-6780&lt;/a&gt;, only contracts created within the same transaction may be fully deleted; this EIP does not reprice or modify any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; side effects.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sat, 11 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-2780</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-2780</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Slashing Protection Interchange Format</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #3076 - Slashing Protection Interchange Format&lt;/strong&gt; is in Last Call status. It is authored by Michael Sproul (@michaelsproul), Sacha Saint-Leger (@sachayves), Danny Ryan (@djrtwo) and was originally created 2020-10-27. It is in the Interface category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-3076-validator-client-interchange-format-slashing-protection/4883&quot;&gt;https://ethereum-magicians.org/t/eip-3076-validator-client-interchange-format-slashing-protection/4883&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;A standard format for transferring a key’s signing history allows validators to easily switch between clients without the risk of signing conflicting messages. While a common keystore format provides part of the solution, it does not contain any information about a key’s signing history. For a validator moving their keys from client A to client B, this could lead to scenarios in which client B inadvertently signs a message that conflicts with an earlier message signed with client A. The interchange format described here provides a solution to this problem.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;The proof of stake (PoS) protocol penalises validators for voting in ways that could result in two different versions of the chain being finalised. These types of penalties are called slashings.&lt;/p&gt;

&lt;p&gt;For a validator following the protocol correctly, there is, in principle, no risk of being slashed. However, changing clients (from client A to client B, say) can result in a slashing risk if client B is unaware of the blocks and attestations that were signed with client A.&lt;/p&gt;

&lt;p&gt;This can occur if client A and client B do not agree on what the present time is. For example, say client A’s time is accidentally set to a day in the future (225 epochs), and a validator switches from client A to client B without giving B a record of the blocks and attestations signed with A. The validator in question now runs the risk of attesting to two different blocks in the same epoch (a slashable offence) for the next 225 epochs (since they’ve already voted on these epochs with client A, and now stand to vote on them again with client B). Such time-skew bugs have been observed in the wild.&lt;/p&gt;

&lt;p&gt;Another situation in which slashing protection is critical is in the case of re-orgs. During a re-org it is possible for a validator to be assigned new attestation duties for an epoch in which it has already signed an attestation. In this case it is essential that the record of the previous attestation is available, even if the validator just moved from one client to another in the space of a single epoch.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;json-schema&quot;&gt;JSON Schema&lt;/h3&gt;

&lt;p&gt;A valid interchange file is one that adheres to the following JSON schema, and is interpreted according to the &lt;a href=&quot;#conditions&quot;&gt;Conditions&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Signing history&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;This schema provides a record of the blocks and attestations signed by a set of validators&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;interchange_format_version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The version of the interchange format that this document adheres to&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;genesis_validators_root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Calculated at Genesis time; serves to uniquely identify the chain&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;interchange_format_version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;genesis_validators_root&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;pubkey&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The BLS public key of the validator (encoded as a 0x-prefixed hex string)&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;signed_blocks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;slot&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The slot number of the block that was signed&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;signing_root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The output of compute_signing_root(block, domain)&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;slot&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;signed_attestations&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;source_epoch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The attestation.data.source.epoch of the signed attestation&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;target_epoch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The attestation.data.target.epoch of the signed attestation&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;signing_root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The output of compute_signing_root(attestation, domain)&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;source_epoch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;target_epoch&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pubkey&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;signed_blocks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;signed_attestations&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;example-json-instance&quot;&gt;Example JSON Instance&lt;/h3&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;interchange_format_version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;genesis_validators_root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0x04700007fabc8282644aed6d1c7c9e21d38a03a0c4ba193f3afe428824b3a673&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;pubkey&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0xb845089a1457f811bfc000588fbb4e713669be8ce060ea6be3c6ece09afc3794106c91ca73acda5e5457122d58723bed&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;signed_blocks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;slot&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;81952&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;signing_root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0x4ff6f743a43f3b4f95350831aeaf0a122a1a392922c45d804280284a69eb850b&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;slot&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;81951&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;signed_attestations&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;source_epoch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2290&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;target_epoch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;3007&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;signing_root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0x587d6a4f59a58fe24f406e0502413e77fe1babddee641fda30034ed37ecc884d&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;source_epoch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2290&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;target_epoch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;3008&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;conditions&quot;&gt;Conditions&lt;/h3&gt;

&lt;p&gt;After importing an interchange file with data field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt;, a signer must respect the following conditions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Refuse to sign any block that is slashable with respect to the blocks contained in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data.signed_blocks&lt;/code&gt;. For details of what constitutes a slashable block, see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_proposer_slashing&lt;/code&gt; (from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consensus-specs&lt;/code&gt;). If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signing_root&lt;/code&gt; is absent from a block, a signer must assume that any new block with the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slot&lt;/code&gt; is slashable with respect to the imported block.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Refuse to sign any block with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slot &amp;lt;= min(b.slot for b in data.signed_blocks if b.pubkey == proposer_pubkey)&lt;/code&gt;, except if it is a repeat signing as determined by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signing_root&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Refuse to sign any attestation that is slashable with respect to the attestations contained in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data.signed_attestations&lt;/code&gt;. For details of what constitutes a slashable attestation, see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_slashable_attestation_data&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Refuse to sign any attestation with source epoch less than the minimum source epoch present in that signer’s attestations (as seen in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data.signed_attestations&lt;/code&gt;). In pseudocode:&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;&lt;code class=&quot;language-python3&quot;&gt;source.epoch &amp;lt;
    min(att.source_epoch
        for att in data.signed_attestations
        if att.pubkey == attester_pubkey)
&lt;/code&gt;&lt;/pre&gt;

&lt;ol start=&quot;5&quot;&gt;
  &lt;li&gt;Refuse to sign any attestation with target epoch less than or equal to the minimum target epoch present in that signer’s attestations (as seen in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data.signed_attestations&lt;/code&gt;), except if it is a repeat signing as determined by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signing_root&lt;/code&gt;. In pseudocode:&lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;&lt;code class=&quot;language-python3&quot;&gt;target_epoch &amp;lt;=
    min(att.target_epoch
        for att in data.signed_attestations
        if att.pubkey == attester_pubkey)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;additional-information&quot;&gt;Additional Information&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interchange_format_version&lt;/code&gt; version is set to 5.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A signed block or attestation’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signing_root&lt;/code&gt; refers to the message data (hash tree root) that gets signed with a BLS signature. It allows validators to re-sign and re-broadcast blocks or attestations if asked.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signed_blocks&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signing_root&lt;/code&gt;s are calculated using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compute_signing_root(block, domain)&lt;/code&gt;: where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block&lt;/code&gt; is the block (of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconBlock&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconBlockHeader&lt;/code&gt;) that was signed, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;domain&lt;/code&gt; is equal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compute_domain(DOMAIN_BEACON_PROPOSER, fork, metadata.genesis_validators_root)&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signed_attestations&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signing_root&lt;/code&gt;s are calculated using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compute_signing_root(attestation, domain)&lt;/code&gt;: where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestation&lt;/code&gt; is the attestation (of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttestationData&lt;/code&gt;) that was signed, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;domain&lt;/code&gt; is equal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compute_domain(DOMAIN_BEACON_ATTESTER, fork, metadata.genesis_validators_root)&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;supporting-different-strategies&quot;&gt;Supporting Different Strategies&lt;/h3&gt;

&lt;p&gt;The interchange format is designed to be flexible enough to support the full variety of slashing protection strategies that clients may implement, which may be categorised into two main types:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Complete&lt;/strong&gt;: a database containing every message signed by each validator.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Minimal&lt;/strong&gt;: a database containing only the latest messages signed by each validator.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The advantage of the minimal strategy is its simplicity and succinctness. Using only the latest messages for each validator, safe slashing protection can be achieved by refusing to sign messages for slots or epochs prior.&lt;/p&gt;

&lt;p&gt;On the other hand, the complete strategy can provide safe slashing protection while also avoiding false positives (meaning that it only prevents a validator from signing if doing so would guarantee a slashing).&lt;/p&gt;

&lt;p&gt;The two strategies are unified in the interchange format through the inclusion of &lt;a href=&quot;#conditions&quot;&gt;conditions&lt;/a&gt; (2), (4) and (5). This allows the interchange to transfer detailed or succinct information, as desired.&lt;/p&gt;

&lt;h3 id=&quot;integer-representation&quot;&gt;Integer Representation&lt;/h3&gt;

&lt;p&gt;Most fields in the JSON schema are strings. For fields in which it is possible to encode the value as either a string or an integer, strings were chosen. This choice was made in order to avoid issues with different languages supporting different ranges of integers (specifically JavaScript, where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; type is a 64-bit float). If a validator is yet to sign a block or attestation, the relevant list is simply left empty.&lt;/p&gt;

&lt;h3 id=&quot;versioning&quot;&gt;Versioning&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interchange_format_version&lt;/code&gt; is set to 5 because the specification went through several breaking changes during its design, incorporating feedback from implementers.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This specification is not backwards-compatible with previous draft versions that used version numbers less than 5.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;In order to minimise risk and complexity, the format has been designed to map cleanly onto the internal database formats used by implementers. Nevertheless, there are a few pitfalls worth illuminating.&lt;/p&gt;

&lt;h3 id=&quot;advice-for-complete-databases&quot;&gt;Advice for Complete Databases&lt;/h3&gt;

&lt;p&gt;For implementers who use a complete record of signed messages to implement their slashing protection database, we make the following recommendations:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You MUST ensure that, in addition to importing all of the messages from an interchange, all the &lt;a href=&quot;#conditions&quot;&gt;conditions&lt;/a&gt; are enforced. In particular, conditions (2), (4) and (5) may not have been enforced by your implementation before adopting the interchange format. Our recommendation is to enforce these rules at all times, to keep the implementation clean and minimise the attack surface. For example: your slashing protection mechanism should not sign a block with a slot number less than, or equal to, the minimum slot number of a previously signed block, &lt;em&gt;irrespective&lt;/em&gt; of whether that minimum-slot block was imported from an interchange file, or inserted as part of your database’s regular operation.&lt;/li&gt;
  &lt;li&gt;If your database records the signing roots of messages in addition to their slot/epochs, you should ensure that imported messages without signing roots are assigned a suitable dummy signing root internally. We suggest using a special “null” value which is distinct from all other signing roots, although a value like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0&lt;/code&gt; may be used instead (as it is extremely unlikely to collide with any real signing root).&lt;/li&gt;
  &lt;li&gt;Care must be taken to avoid signing messages within a gap in the database (an area of unknown signing activity). This could occur if two interchanges were imported with a large gap between the last entry of the first and the first entry of the second. Signing in this gap is not safe, and would violate conditions (2), (4) and (5). It can be avoided by storing an explicit low watermark in addition to the actual messages of the slashing protection database, or by pruning on import so that the oldest messages from the interchange become the oldest messages in the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;advice-for-minimal-databases&quot;&gt;Advice for Minimal Databases&lt;/h3&gt;

&lt;p&gt;For implementers who wish to implement their slashing protection database by storing only the latest block and attestation for each validator, we make the following recommendations:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;During import, make sure you take the &lt;em&gt;maximum&lt;/em&gt; slot block and &lt;em&gt;maximum&lt;/em&gt; source and target attestations for each validator. Although the &lt;a href=&quot;#conditions&quot;&gt;conditions&lt;/a&gt; require the minimums to be enforced, taking the maximums from an interchange file and merging them with any existing values in the database is the recommended approach. For example, if the interchange file includes blocks for validator &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;V&lt;/code&gt; at slots 4, 98 and 243, then the latest signed block for validator &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;V&lt;/code&gt; should be updated to the one from slot 243.  However, if the database has already included a block for this validator at a slot greater than 243, for example, slot 351, then the database’s existing value should remain unchanged.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;general-recommendations&quot;&gt;General Recommendations&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;To avoid exporting an outdated interchange file – an action which creates a slashing risk – your implementation should only allow the slashing protection database to be exported when the validator client or signer is &lt;em&gt;stopped&lt;/em&gt; – in other words, when the client or signer is no longer adding new messages to the database.&lt;/li&gt;
  &lt;li&gt;Similarly, your implementation should only allow an interchange file to be imported when the validator client is stopped.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Tue, 27 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-3076</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-3076</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>EVM trace specification</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #3155 - EVM trace specification&lt;/strong&gt; is in Last Call status. It is authored by Martin Holst Swende (@holiman), Marius van der Wijden (@MariusVanDerWijden) and was originally created 2020-12-07. It is in the Interface category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-3155-create-evm-trace-specification/5007&quot;&gt;https://ethereum-magicians.org/t/eip-3155-create-evm-trace-specification/5007&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;Introduce a new JSON standard for EVM traces during execution of state tests.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;The Ethereum Virtual Machine executes all smart contract code on ethereum.
In order to debug smart contracts and state tests better, a common format was introduced to log every execution step of the EVM.
This format was implemented by Go-Ethereum, Parity-Ethereum, Nethermind and Besu.
Since the common format was not well-defined, the implementations differed slightly, making it hard to develop adequate tooling which reduces the usefulness of tracing significantly.&lt;/p&gt;

&lt;p&gt;This EIP has multiple goals:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Move the specification to a more visible place to encourage new clients to implement it&lt;/li&gt;
  &lt;li&gt;Strictly define corner cases that were not addressed in the previous version&lt;/li&gt;
  &lt;li&gt;Allow for updates to the specification in case new fields are introduced during execution&lt;/li&gt;
  &lt;li&gt;Provide sample output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implementing this EIP in all major clients allows us to create meaningful differential fuzzers that fuzz EVM implementations for the mainnet and all upcoming hardforks.
It also helps to find differences in execution quickly in the case of a chain split.&lt;/p&gt;

&lt;p&gt;This EIP will enable users to create better differential fuzzing infrastructure to compare the EVM implementations of all major Ethereum clients against each other.
This could help to find bugs that are currently present in the client implementations.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;Clients should be able to execute simple transactions as well as code and return traces. In the following, we will call this client CUT (client under test) and use go-ethereum’s
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm&lt;/code&gt; binary for code examples.&lt;/p&gt;

&lt;h3 id=&quot;datatypes&quot;&gt;Datatypes&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
      &lt;th&gt;Example&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Number&lt;/td&gt;
      &lt;td&gt;Plain json number&lt;/td&gt;
      &lt;td&gt;“pc”:0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hex-Number&lt;/td&gt;
      &lt;td&gt;Hex-encoded number&lt;/td&gt;
      &lt;td&gt;“gas”:”0x2540be400”&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;String&lt;/td&gt;
      &lt;td&gt;Plain string&lt;/td&gt;
      &lt;td&gt;“opName”:”PUSH1”&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hex-String&lt;/td&gt;
      &lt;td&gt;Hex-encoded string&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Array of x&lt;/td&gt;
      &lt;td&gt;Array of x encoded values&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Key-Value&lt;/td&gt;
      &lt;td&gt;Key-Value structure with key and values encoded as hex strings&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Boolean&lt;/td&gt;
      &lt;td&gt;Json bool can either be true or false&lt;/td&gt;
      &lt;td&gt;“pass”: true&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;output&quot;&gt;Output&lt;/h3&gt;

&lt;p&gt;The CUT MUST output a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;json&lt;/code&gt; object for EACH operation.&lt;/p&gt;

&lt;h4 id=&quot;required-fields&quot;&gt;Required Fields&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pc&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Number&lt;/td&gt;
      &lt;td&gt;Program Counter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;op&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Number&lt;/td&gt;
      &lt;td&gt;OpCode&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Hex-Number&lt;/td&gt;
      &lt;td&gt;Gas left before executing this operation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gasCost&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Hex-Number&lt;/td&gt;
      &lt;td&gt;Gas cost of this operation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memSize&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Number&lt;/td&gt;
      &lt;td&gt;Size of memory array&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Array of Hex-Numbers&lt;/td&gt;
      &lt;td&gt;Array of all values on the stack&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;depth&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Number&lt;/td&gt;
      &lt;td&gt;Depth of the call stack&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;returnData&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Hex-String&lt;/td&gt;
      &lt;td&gt;Data returned by function call&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;refund&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Number&lt;/td&gt;
      &lt;td&gt;Amount of &lt;strong&gt;global&lt;/strong&gt; gas refunded&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;optional-fields&quot;&gt;Optional Fields&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opName&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;String&lt;/td&gt;
      &lt;td&gt;Name of the operation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;error&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Hex-String&lt;/td&gt;
      &lt;td&gt;Description of an error (should contain revert reason if supported)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Array of Hex-Strings&lt;/td&gt;
      &lt;td&gt;Array of all allocated values&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Key-Value&lt;/td&gt;
      &lt;td&gt;Array of all stored values&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{&quot;pc&quot;:0,&quot;op&quot;:96,&quot;gas&quot;:&quot;0x2540be400&quot;,&quot;gasCost&quot;:&quot;0x3&quot;,&quot;memory&quot;:&quot;0x&quot;,&quot;memSize&quot;:0,&quot;stack&quot;:[],&quot;depth&quot;:1,&quot;error&quot;:null,&quot;opName&quot;:&quot;PUSH1&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memSize&lt;/code&gt; are the values &lt;em&gt;before&lt;/em&gt; execution of the op.&lt;/li&gt;
  &lt;li&gt;All array attributes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory&lt;/code&gt;) MUST be initialized to empty arrays (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;stack&quot;:[]&lt;/code&gt;) NOT to null.&lt;/li&gt;
  &lt;li&gt;If the CUT will not be outputting values for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage&lt;/code&gt; then the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage&lt;/code&gt; fields are omitted.
This can happen either because the CUT does not support tracing these fields or it has been configured not to trace it.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memSize&lt;/code&gt; field MUST be present regardless of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory&lt;/code&gt; support.&lt;/li&gt;
  &lt;li&gt;Clients SHOULD implement a way to disable recording the storage as the stateroot includes all storage updates.&lt;/li&gt;
  &lt;li&gt;Clients SHOULD output the fields in the same order as listed in this EIP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CUT MUST NOT output a line for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STOP&lt;/code&gt; operation if an error occurred:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{&quot;pc&quot;:2,&quot;op&quot;:0,&quot;gas&quot;:&quot;0x2540be3fd&quot;,&quot;gasCost&quot;:&quot;0x0&quot;,&quot;memory&quot;:&quot;0x&quot;,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x40&quot;],&quot;depth&quot;:1,&quot;error&quot;:null,&quot;opName&quot;:&quot;STOP&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;summary-and-error-handling&quot;&gt;Summary and Error Handling&lt;/h3&gt;

&lt;p&gt;At the end of execution, the CUT MUST print summary info; this info SHOULD have the following fields.
The summary should be a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jsonl&lt;/code&gt; object.&lt;/p&gt;

&lt;h4 id=&quot;required-fields-1&quot;&gt;Required Fields&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stateRoot&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Hex-String&lt;/td&gt;
      &lt;td&gt;Root of the state trie after executing the transaction&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;output&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Return values of the function&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gasUsed&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Hex-Number&lt;/td&gt;
      &lt;td&gt;All gas used by the transaction&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pass&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Boolean&lt;/td&gt;
      &lt;td&gt;Bool whether transaction was executed successfully&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;optional-fields-1&quot;&gt;Optional Fields&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;time&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Number&lt;/td&gt;
      &lt;td&gt;Time in nanoseconds needed to execute the transaction&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;String&lt;/td&gt;
      &lt;td&gt;Name of the fork rules used for execution&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;em&gt;Example&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{&quot;stateRoot&quot;:&quot;0xd4c577737f5d20207d338c360c42d3af78de54812720e3339f7b27293ef195b7&quot;,&quot;output&quot;:&quot;&quot;,&quot;gasUsed&quot;:&quot;0x3&quot;,&quot;pass&quot;:&quot;true&quot;,&quot;time&quot;:141485}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;This EIP is largely based on the previous non-official documentation for EVM tracing.
It tries to cover as many corner cases as possible to enable true client compatibility.
The datatypes and if a field is optional is chosen to be as compatible with current implementations as possible.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP is fully backward compatible with ethereum as it only introduces a better tracing infrastructure that is optional for clients to implement.&lt;/p&gt;

&lt;h3 id=&quot;clients&quot;&gt;Clients&lt;/h3&gt;

&lt;p&gt;This EIP is fully backward compatible with go-ethereum. OpenEthereum, Besu and Nethermind clients would have to change their JSON output of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openethereum-evm&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evmtool&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nethtest&lt;/code&gt; slightly do adhere to the new and stricter specs. New clients would need to implement this change if they want to be part of the differential fuzzing group.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BESU_HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin/evmtool &lt;span class=&quot;nt&quot;&gt;--code&lt;/span&gt; 0x604080536040604055604060006040600060025afa6040f3 &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540be400&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[],&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;PUSH1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:2,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:128,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540be3fd&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;DUP1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:3,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:83,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540be3fa&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0xc&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;MSTORE8&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:4,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540be3ee&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[],&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;PUSH1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:6,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540be3eb&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;PUSH1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:8,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:85,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540be3e8&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x4e20&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;SSTORE&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:9,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b95c8&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[],&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;PUSH1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:11,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b95c5&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;PUSH1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:13,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b95c2&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;PUSH1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:15,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b95bf&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x0&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;PUSH1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:17,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b95bc&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x0&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;PUSH1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:19,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:90,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b95b9&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x0&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x0&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;GAS&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:20,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:250,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b95b7&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x24abb676c&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x0&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x0&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x2&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b95b7&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;STATICCALL&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:21,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b92a7&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x3&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;returnData&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;PUSH1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pc&quot;&lt;/span&gt;:23,&lt;span class=&quot;s2&quot;&gt;&quot;op&quot;&lt;/span&gt;:243,&lt;span class=&quot;s2&quot;&gt;&quot;gas&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x2540b92a4&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasCost&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x0&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memory&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;memSize&quot;&lt;/span&gt;:96,&lt;span class=&quot;s2&quot;&gt;&quot;stack&quot;&lt;/span&gt;:[&lt;span class=&quot;s2&quot;&gt;&quot;0x1&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;returnData&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;depth&quot;&lt;/span&gt;:1,&lt;span class=&quot;s2&quot;&gt;&quot;refund&quot;&lt;/span&gt;:0,&lt;span class=&quot;s2&quot;&gt;&quot;opName&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;RETURN&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;stateRoot&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x8fa0dcc7f1d2383c89e5737c2843632db881c0946e80b71fe7175365e6538797&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;output&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x40&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;gasUsed&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;0x515c&quot;&lt;/span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;pass&quot;&lt;/span&gt;:true,&lt;span class=&quot;s2&quot;&gt;&quot;fork&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;Istanbul&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;Tracing is expensive.&lt;/p&gt;

&lt;p&gt;Exposing an endpoint for creating traces publicly could open up a denial of service vector.&lt;/p&gt;

&lt;p&gt;Clients should consider putting trace endpoints behind a separate flag from other endpoints.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Mon, 07 Dec 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-3155</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-3155</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>ERC-721 Nonce Extension</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #5008 - ERC-721 Nonce Extension&lt;/strong&gt; is in Last Call status. It is authored by Anders (@0xanders), Lance (@LanceSnow), Shrug &lt;shrug@emojidao.org&gt; and was originally created 2022-04-10. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip5008-eip-721-nonce-and-metadata-update-extension/8925&quot;&gt;https://ethereum-magicians.org/t/eip5008-eip-721-nonce-and-metadata-update-extension/8925&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This standard is an extension of &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt;. It proposes adding a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt; function to ERC-721 tokens.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Some orders of NFT marketplaces have been attacked and the NFTs sold at a lower price than the current market floor price. This can happen when users transfer an NFT to another wallet and, later, back to the original wallet. This reactivates the order, which may list the token at a much lower price than the owner would have intended.&lt;/p&gt;

&lt;p&gt;This EIP proposes adding a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt; property to ERC-721 tokens, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt; will be changed when a token is transferred. If a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt; is added to an order, the order can be checked to avoid attacks.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY” and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c1&quot;&gt;/// @dev the ERC-165 identifier for this interface is 0xce03fdab.
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5008&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* is IERC165 */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;/// @notice Emitted when the `nonce` of an NFT is changed
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NonceChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Get the nonce of an NFT
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// Throws if `tokenId` is not a valid NFT
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param tokenId The id of the NFT
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return The nonce of the NFT
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce(uint256 tokenId)&lt;/code&gt; function MUST be implemented as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;view&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface&lt;/code&gt; method MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; when called with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xce03fdab&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;At first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferCount&lt;/code&gt; was considered as function name, but there may some case to change the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt; besides transfer, such as important properties changed, then we changed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferCount&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This standard is compatible with ERC-721.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Test cases are included in &lt;a href=&quot;/assets/eip-5008/test/test.ts&quot;&gt;test.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ../assets/eip-5008
npm &lt;span class=&quot;nb&quot;&gt;install
&lt;/span&gt;npm run &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;See &lt;a href=&quot;/assets/eip-5008/contracts/ERC5008.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC5008.sol&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;No security issues found.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sun, 10 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-5008</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-5008</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Soulbound Badge</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #5114 - Soulbound Badge&lt;/strong&gt; is in Last Call status. It is authored by Micah Zoltu (@MicahZoltu) and was originally created 2022-05-30. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-5114-soulbound-token/9417&quot;&gt;https://ethereum-magicians.org/t/eip-5114-soulbound-token/9417&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;A soulbound badge is a token that, when minted, is bound to another Non-Fungible Token (NFT), and cannot be transferred/moved after that.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5114&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// fired anytime a new instance of this badge is minted
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// this event **MUST NOT** be fired twice for the same `badgeId`
&lt;/span&gt;	&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Mint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;badgeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nftAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nftTokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;// returns the NFT that this badge is bound to.
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// this function **MUST** throw if the badge hasn&apos;t been minted yet
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// this function **MUST** always return the same result every time it is called after it has been minted
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// this function **MUST** return the same value as found in the original `Mint` event for the badge
&lt;/span&gt;	&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ownerOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;badgeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nftAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nftTokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;// returns a URI with details about this badge collection
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// the metadata returned by this is merged with the metadata return by `badgeUri(uint256)`
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// the collectionUri **MUST** be immutable (e.g., ipfs:// and not http://)
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// the collectionUri **MUST** be content addressable (e.g., ipfs:// and not http://)
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// data from `badgeUri` takes precedence over data returned by this method
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// any external links referenced by the content at `collectionUri` also **MUST** follow all of the above rules
&lt;/span&gt;	&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collectionUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collectionUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;// returns a censorship resistant URI with details about this badge instance
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// the collectionUri **MUST** be immutable (e.g., ipfs:// and not http://)
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// the collectionUri **MUST** be content addressable (e.g., ipfs:// and not http://)
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// data from this takes precedence over data returned by `collectionUri`
&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// any external links referenced by the content at `badgeUri` also **MUST** follow all of the above rules
&lt;/span&gt;	&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;badgeUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;badgeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;badgeUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;// returns a string that indicates the format of the `badgeUri` and `collectionUri` results (e.g., &apos;EIP-ABCD&apos; or &apos;soulbound-schema-version-4&apos;)
&lt;/span&gt;	&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadataFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Implementers of this standard &lt;strong&gt;SHOULD&lt;/strong&gt; also depend on a standard for interface detection so callers can easily find out if a given contract implements this interface.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;immutability&quot;&gt;Immutability&lt;/h3&gt;

&lt;p&gt;By requiring that badges can never move, we both guarantee non-separability and non-mergeability among collections of soulbound badges that are bound to a single NFT while simultaneously allowing users to aggressively cache results.&lt;/p&gt;

&lt;h3 id=&quot;content-addressable-uris-required&quot;&gt;Content Addressable URIs Required&lt;/h3&gt;

&lt;p&gt;Soulbound badges are meant to be permanent badges/indicators attached to a persona.
This means that not only can the user not transfer ownership, but the minter also cannot withdraw/transfer/change ownership as well.
This includes mutating or removing any remote content as a means of censoring or manipulating specific users.&lt;/p&gt;

&lt;h3 id=&quot;no-specification-for-badgeuri-data-format&quot;&gt;No Specification for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;badgeUri&lt;/code&gt; Data Format&lt;/h3&gt;

&lt;p&gt;The format of the data pointed to by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collectionUri()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;badgeUri(uint256)&lt;/code&gt;, and how to merge them, is intentionally left out of this standard in favor of separate standards that can be iterated on in the future.
The immutability constraints are the only thing defined by this to ensure that the spirit of this badge is maintained, regardless of the specifics of the data format.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadataFormat&lt;/code&gt; function can be used to inform a caller what type/format/version of data they should expect at the URIs, so the caller can parse the data directly without first having to deduce its format via inspection.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This is a new token type and is not meant to be backward compatible with any existing tokens other than existing viable souls (any asset that can be identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[address,id]&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;Users of badges that claim to implement this EIP must be diligent in verifying they actually do.
A badge author can create a badge that, upon initial probing of the API surface, may appear to follow the rules when in reality it doesn’t.
For example, the contract could allow transfers via some mechanism and simply not utilize them initially.&lt;/p&gt;

&lt;p&gt;It should also be made clear that soulbound badges are not bound to a human, they are bound to a persona.
A persona is any actor (which could be a group of humans) that collects multiple soulbound badges over time to build up a collection of badges.
This persona may transfer to another human, or to another group of humans, and anyone interacting with a persona should not assume that there is a single permanent human behind that persona.&lt;/p&gt;

&lt;p&gt;It is possible for a soulbound badge to be bound to another soulbound badge.
In theory, if all badges in the chain are created at the same time they could form a loop.
Software that tries to walk such a chain should take care to have an exit strategy if a loop is detected.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Mon, 30 May 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-5114</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-5114</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Cross-Chain Execution</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #5164 - Cross-Chain Execution&lt;/strong&gt; is in Last Call status. It is authored by Brendan Asselstine (@asselstine), Pierrick Turelier (@PierrickGT), Chris Whinfrey (@cwhinfrey) and was originally created 2022-06-14. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-5164-cross-chain-execution/9658&quot;&gt;https://ethereum-magicians.org/t/eip-5164-cross-chain-execution/9658&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This specification defines a cross-chain execution interface for EVM-based blockchains. Implementations of this specification will allow contracts on one chain to call contracts on another by sending a cross-chain message.&lt;/p&gt;

&lt;p&gt;The specification defines two components: the “Message Dispatcher” and the “Message Executor”. The Message Dispatcher lives on the calling side, and the executor lives on the receiving side. When a message is sent, a Message Dispatcher will move the message through a transport layer to a Message Executor, where they are executed. Implementations of this specification must implement both components.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Many Ethereum protocols need to coordinate state changes across multiple EVM-based blockchains. These chains often have native or third-party bridges that allow Ethereum contracts to execute code. However, bridges have different APIs so bridge integrations are custom. Each one affords different properties; with varying degrees of security, speed, and control. Defining a simple, common specification will increase code re-use and allow us to use common bridge implementations.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.&lt;/p&gt;

&lt;p&gt;This specification allows contracts on one chain to send messages to contracts on another chain. There are two key interfaces that needs to be implemented:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt; lives on the origin chain and dispatches messages to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt; for execution. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt; lives on the destination chain and executes dispatched messages.&lt;/p&gt;

&lt;h3 id=&quot;messagedispatcher&quot;&gt;MessageDispatcher&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt; lives on the chain from which messages are sent. The Dispatcher’s job is to broadcast messages through a transport layer to one or more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt; contracts.&lt;/p&gt;

&lt;p&gt;A unique &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;messageId&lt;/code&gt; MUST be generated for each message or message batch. The message identifier MUST be unique across chains and dispatchers.  This can be achieved by hashing a tuple of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chainId, dispatcherAddress, messageNonce&lt;/code&gt; where messageNonce is a monotonically increasing integer per message.&lt;/p&gt;

&lt;h4 id=&quot;messagedispatcher-methods&quot;&gt;MessageDispatcher Methods&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;dispatchMessage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Will dispatch a message to be executed by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt; on the destination chain specified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toChainId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt;s MUST emit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatched&lt;/code&gt; event when a message is dispatched.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt;s MUST revert if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toChainId&lt;/code&gt; is not supported.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt;s MUST forward the message to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt; on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toChainId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt;s MUST use a unique &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;messageId&lt;/code&gt; for each message.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt;s MUST return the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;messageId&lt;/code&gt; to allow the message sender to track the message.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt;s MAY require payment.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageDispatcher&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dispatchMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toChainId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messageId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;dispatchMessage&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;function&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;stateMutability&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;payable&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;toChainId&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;uint256&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;to&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;address&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;data&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bytes&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;outputs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;messageId&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bytes32&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;messagedispatcher-events&quot;&gt;MessageDispatcher Events&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;MessageDispatched&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatched&lt;/code&gt; event MUST be emitted by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt; when an individual message is dispatched.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageDispatcher&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageDispatched&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messageId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toChainId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MessageDispatched&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;event&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;messageId&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;indexed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bytes32&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;from&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;indexed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;address&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;toChainId&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;indexed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;uint256&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;to&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;address&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;data&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bytes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;messageexecutor&quot;&gt;MessageExecutor&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt; executes dispatched messages and message batches. Developers must implement a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt; in order to execute messages on the receiving chain.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt; will execute a messageId only once, but may execute messageIds in any order. This specification makes no ordering guarantees, because messages and message batches may travel non-sequentially through the transport layer.&lt;/p&gt;

&lt;h4 id=&quot;execution&quot;&gt;Execution&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt;s SHOULD verify all message data with the bridge transport layer.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt;s MUST NOT successfully execute a message more than once.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt;s MUST revert the transaction when a message fails to be executed allowing the message to be retried at a later time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calldata&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt;s MUST append the ABI-packed (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;messageId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fromChainId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt;) to the calldata for each message being executed. This allows the receiver of the message to verify the cross-chain sender and the chain that the message is coming from.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messageId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromChainId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;calldata&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bytes&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;data&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bytes&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;messageId&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bytes32&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;fromChainId&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;uint256&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;from&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;address&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;messageexecutor-events&quot;&gt;MessageExecutor Events&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;MessageIdExecuted&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageIdExecuted&lt;/code&gt; MUST be emitted once a message or message batch has been executed.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageExecutor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageIdExecuted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromChainId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messageId&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MessageIdExecuted&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;event&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;fromChainId&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;indexed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;uint256&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;messageId&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;indexed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bytes32&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;messageexecutor-errors&quot;&gt;MessageExecutor Errors&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;MessageAlreadyExecuted&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt;s MUST revert if a messageId has already been executed and SHOULD emit a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageIdAlreadyExecuted&lt;/code&gt; custom error.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageExecutor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageIdAlreadyExecuted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messageId&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;MessageFailure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt;s MUST revert if an individual message fails and SHOULD emit a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageFailure&lt;/code&gt; custom error.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageExecutor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageFailure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messageId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;errorData&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageDispatcher&lt;/code&gt; can be coupled to one or more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt;. It is up to bridges to decide how to couple the two. Users can easily bridge a message by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dispatchMessage&lt;/code&gt; without being aware of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageExecutor&lt;/code&gt; address. Messages can also be traced by a client using the data logged by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageIdExecuted&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;Some bridges may require payment in the native currency, so the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dispatchMessage&lt;/code&gt; function is payable.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This specification is compatible with existing governance systems as it offers simple cross-chain execution.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;Bridge trust profiles are variable, so users must understand that bridge security depends on the implementation.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Tue, 14 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-5164</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-5164</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>ERC-1155 Allowance Extension</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #5216 - ERC-1155 Allowance Extension&lt;/strong&gt; is in Last Call status. It is authored by Iván Mañús (@ivanmmurciaua), Juan Carlos Cantó (@EscuelaCryptoES) and was originally created 2022-07-11. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-erc1155-approval-by-amount/9898&quot;&gt;https://ethereum-magicians.org/t/eip-erc1155-approval-by-amount/9898&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This ERC defines standard functions for granular approval of &lt;a href=&quot;/EIPS/eip-1155&quot;&gt;ERC-1155&lt;/a&gt; tokens by both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount&lt;/code&gt;. This ERC extends &lt;a href=&quot;/EIPS/eip-1155&quot;&gt;ERC-1155&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-1155&quot;&gt;ERC-1155&lt;/a&gt;’s popularity means that multi-token management transactions occur on a daily basis. Although it can be used as a more comprehensive alternative to &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt;, ERC-1155 is most commonly used as intended: creating multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;s, each with multiple tokens. While many projects interface with these semi-fungible tokens, by far the most common interactions are with NFT marketplaces.&lt;/p&gt;

&lt;p&gt;Due to the nature of the blockchain, programming errors or malicious operators can cause permanent loss of funds. It is therefore essential that transactions are as trustless as possible. ERC-1155 uses the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setApprovalForAll&lt;/code&gt; function, which approves ALL tokens with a specific &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;. This system has obvious minimum required trust flaws. This ERC combines ideas from &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt; in order to create a trust mechanism where an owner can allow a third party, such as a marketplace, to approve a limited (instead of unlimited) number of tokens of one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.&lt;/p&gt;

&lt;p&gt;Contracts using this ERC MUST implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC5216&lt;/code&gt; interface.&lt;/p&gt;

&lt;h3 id=&quot;interface-implementation&quot;&gt;Interface implementation&lt;/h3&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
 * @title ERC-1155 Allowance Extension
 * Note: the ERC-165 identifier for this interface is 0x1be07d74
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5216&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC1155&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `id` and with an amount: `amount`.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Approval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;account&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Grants permission to `operator` to transfer the caller&apos;s tokens, according to `id`, and an amount: `amount`.
     * Emits an {Approval} event.
     *
     * Requirements:
     * - `operator` cannot be the caller.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;approve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Returns the amount allocated to `operator` approved to transfer `account`&apos;s tokens, according to `id`.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allowance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;account&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve(address operator, uint256 id, uint256 amount)&lt;/code&gt; function MUST be either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;external&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowance(address account, address operator, uint256 id)&lt;/code&gt; function MUST be either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;external&lt;/code&gt; and MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;view&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;safeTrasferFrom&lt;/code&gt; function (as defined by ERC-1155) MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Not revert if the user has approved &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; with a sufficient &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Subtract the transferred amount of tokens from the approved amount if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; is not approved with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setApprovalForAll&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;safeBatchTransferFrom&lt;/code&gt; MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add an extra condition that checks if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowance&lt;/code&gt; of all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ids&lt;/code&gt; have the approved &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amounts&lt;/code&gt; (See &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_checkApprovalForBatch&lt;/code&gt; function reference implementation)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Approval&lt;/code&gt; event MUST be emitted when a certain number of tokens are approved.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface&lt;/code&gt; method MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; when called with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x1be07d74&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;The name “ERC-1155 Allowance Extension” was chosen because it is a succinct description of this ERC. Users can approve their tokens by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;operator&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;By having a way to approve and revoke in a manner similar to &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;, the trust level can be more directly managed by users:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve&lt;/code&gt; function, users can approve an operator to spend an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount&lt;/code&gt; of tokens for each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowance&lt;/code&gt; function, users can see the approval that an operator has for each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; name patterns were used due to similarities with &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; approvals.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This standard is compatible with &lt;a href=&quot;/EIPS/eip-1155&quot;&gt;ERC-1155&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;The reference implementation can be found &lt;a href=&quot;/assets/eip-5216/ERC5216.sol&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;Users of this ERC must thoroughly consider the amount of tokens they give permission to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;operators&lt;/code&gt;, and should revoke unused authorizations.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Mon, 11 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-5216</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-5216</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Endorsement - Permit for Any Functions</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #5453 - Endorsement - Permit for Any Functions&lt;/strong&gt; is in Last Call status. It is authored by Zainan Victor Zhou (@xinbenlv) and was originally created 2022-08-12. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-5453-endorsement-standard/10355&quot;&gt;https://ethereum-magicians.org/t/erc-5453-endorsement-standard/10355&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP establishes a general protocol for permitting and approving function calls in the same transaction relying on &lt;a href=&quot;/EIPS/eip-5750&quot;&gt;ERC-5750&lt;/a&gt;.
Unlike a few prior art (&lt;a href=&quot;/EIPS/eip-2612&quot;&gt;ERC-2612&lt;/a&gt; for &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-4494&quot;&gt;ERC-4494&lt;/a&gt; for &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt; that
usually only permit for a single behavior (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfer&lt;/code&gt; for ERC-20 and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;safeTransferFrom&lt;/code&gt; for ERC-721) and a single approver in two transactions (first a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permit(...)&lt;/code&gt; TX, then a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfer&lt;/code&gt;-like TX), this EIP provides a way to permit arbitrary behaviors and aggregating multiple approvals from arbitrary number of approvers in the same transaction, allowing for Multi-Sig or Threshold Signing behavior.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Support permit(approval) alongside a function call.&lt;/li&gt;
  &lt;li&gt;Support a second approval from another user.&lt;/li&gt;
  &lt;li&gt;Support pay-for-by another user&lt;/li&gt;
  &lt;li&gt;Support multi-sig&lt;/li&gt;
  &lt;li&gt;Support persons acting in concert by endorsements&lt;/li&gt;
  &lt;li&gt;Support accumulated voting&lt;/li&gt;
  &lt;li&gt;Support off-line signatures&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.&lt;/p&gt;

&lt;h3 id=&quot;interfaces&quot;&gt;Interfaces&lt;/h3&gt;

&lt;p&gt;The interfaces and structures referenced here are as follows&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ValidityBound&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functionParamStructHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SingleEndorsementData&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorserAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 32
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// dynamic = 65
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GeneralExtensionDataStruct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;erc5453MagicWord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;erc5453Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorsementPayload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5453EndorsementCore&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eip5453Nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isEligibleEndorser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5453EndorsementDigest&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeValidityDigest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_functionParamStructHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_validSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_validBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_nonce&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeFunctionParamHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_functionName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_functionParamPacked&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5453EndorsementDataTypeA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeExtensionDataTypeA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorserAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5453EndorsementDataTypeB&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeExtensionDataTypeB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorserAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sigs&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href=&quot;/assets/eip-5453/IERC5453.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC5453.sol&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;behavior-specification&quot;&gt;Behavior specification&lt;/h3&gt;

&lt;p&gt;As specified in &lt;a href=&quot;/EIPS/eip-5750&quot;&gt;ERC-5750 General Extensibility for Method Behaviors&lt;/a&gt;, any compliant method that has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes extraData&lt;/code&gt; parameter as its
last designated parameter for extending behaviors can conform to &lt;a href=&quot;/EIPS/eip-5453&quot;&gt;ERC-5453&lt;/a&gt; as the way to indicate a permit from a certain user.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Any compliant method of this EIP MUST be a &lt;a href=&quot;/EIPS/eip-5750&quot;&gt;ERC-5750&lt;/a&gt; compliant method.&lt;/li&gt;
  &lt;li&gt;Caller MUST pass in the last parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes extraData&lt;/code&gt; conforming to Solidity memory-encoded bytes of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GeneralExtensionDataStruct&lt;/code&gt; specified in &lt;em&gt;Section Interfaces&lt;/em&gt;. The following descriptions are based on when decoding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes extraData&lt;/code&gt; into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GeneralExtensionDataStruct&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GeneralExtensionDataStruct&lt;/code&gt;-decoded &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extraData&lt;/code&gt;, caller MUST set the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GeneralExtensionDataStruct.erc5453MagicWord&lt;/code&gt; to be the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(&quot;ERC5453-ENDORSEMENT&quot;)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Caller MUST set the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GeneralExtensionDataStruct.erc5453Type&lt;/code&gt; to be one of the supported values.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC5453_TYPE_A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC5453_TYPE_B&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;When the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GeneralExtensionDataStruct.erc5453Type&lt;/code&gt; is set to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC5453_TYPE_A&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GeneralExtensionDataStruct.endorsementPayload&lt;/code&gt; MUST be abi encoded bytes of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SingleEndorsementData&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GeneralExtensionDataStruct.erc5453Type&lt;/code&gt; is set to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC5453_TYPE_B&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GeneralExtensionDataStruct.endorsementPayload&lt;/code&gt; MUST be abi encoded bytes of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SingleEndorsementData[]&lt;/code&gt; (a dynamic array).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SingleEndorsementData&lt;/code&gt; MUST have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address endorserAddress;&lt;/code&gt; and a 65-bytes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes sig&lt;/code&gt; signature.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes sig&lt;/code&gt; MUST be an ECDSA (secp256k1) signature using private key of signer whose corresponding address is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;endorserAddress&lt;/code&gt; signing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validityDigest&lt;/code&gt; which is the hashTypeDataV4 of &lt;a href=&quot;/EIPS/eip-712&quot;&gt;EIP-712&lt;/a&gt; of hashStruct of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValidityBound&lt;/code&gt; data structure as follows:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validityDigest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;eip712HashTypedDataV4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&quot;ValidityBound(bytes32 functionParamStructHash,uint256 validSince,uint256 validBy,uint256 nonce)&quot;&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;functionParamStructHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;_validSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;_validBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;_nonce&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;functionParamStructHash&lt;/code&gt; MUST be computed as follows&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functionParamStructHash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_functionStructure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;_functionParamPacked&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functionParamStructHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;whereas&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_functionStructure&lt;/code&gt; MUST be computed as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function methodName(type1 param1, type2 param2, ...)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_functionParamPacked&lt;/code&gt; MUST be computed as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enc(param1) || enco(param2) ...&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;Upon validating that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;endorserAddress == ecrecover(validityDigest, signature)&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EIP1271(endorserAddress).isValidSignature(validityDigest, signature) == ERC1271.MAGICVALUE&lt;/code&gt;, the single endorsement MUST be deemed valid.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Compliant method MAY choose to impose a threshold for a number of endorsements needs to be valid in the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC5453_TYPE_B&lt;/code&gt; kind of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;endorsementPayload&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validSince&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validBy&lt;/code&gt; are both inclusive. Implementer MAY choose to use blocknumber or timestamp. Implementors SHOULD find a way to indicate whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validSince&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validBy&lt;/code&gt; is blocknumber or timestamp.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;We chose to have both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC5453_TYPE_A&lt;/code&gt;(single-endorsement) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC5453_TYPE_B&lt;/code&gt;(multiple-endorsements, same nonce for entire contract) so we
could balance a wider range of use cases. E.g. the same use cases of ERC-2612 and &lt;a href=&quot;/EIPS/eip-4494&quot;&gt;ERC-4494&lt;/a&gt; can be supported by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC5453_TYPE_A&lt;/code&gt;. And threshold approvals can be done via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC5453_TYPE_B&lt;/code&gt;. More complicated approval types can also be extended by defining new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC5453_TYPE_?&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We chose to include both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validSince&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validBy&lt;/code&gt; to allow maximum flexibility in expiration. This can also be supported natively by the EVM if &lt;a href=&quot;/EIPS/eip-5081&quot;&gt;ERC-5081&lt;/a&gt; is adopted, but &lt;a href=&quot;/EIPS/eip-5081&quot;&gt;ERC-5081&lt;/a&gt; will not be adopted anytime soon, so we choose to add these two numbers in our protocol to allow
smart contract level support.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;The design assumes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes calldata extraData&lt;/code&gt; to maximize the flexibility of future extensions. This assumption is compatible with &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-1155&quot;&gt;ERC-1155&lt;/a&gt; and many other ERC-track EIPs. Those that aren’t, such as &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;, can also be updated to support it, such as using a wrapper contract or proxy upgrade.&lt;/p&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;In addition to the specified algorithm for validating endorser signatures, we also present the following reference implementations.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@openzeppelin/contracts/utils/cryptography/EIP712.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;./IERC5453.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AERC5453Endorsible&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EIP712&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IERC5453EndorsementCore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5453EndorsementDigest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5453EndorsementDataTypeA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5453EndorsementDataTypeB&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_validate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msgDigest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;SingleEndorsementData&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endersement&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;endersement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;65&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;AERC5453Endorsible: wrong signature length&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;SignatureChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isValidSignatureNow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;endersement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endorserAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;msgDigest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;endersement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;AERC5453Endorsible: invalid signature&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;modifier&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onlyEndorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_functionParamStructHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_extensionData&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_isEndorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_functionParamStructHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_extensionData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeExtensionDataTypeB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorserAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sigs&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endorserAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sigs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;SingleEndorsementData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorsements&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SingleEndorsementData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[](&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;endorserAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorserAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;endorsements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SingleEndorsementData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;endorserAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sigs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;GeneralExtensionDataStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;MAGIC_WORLD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;ERC5453_TYPE_B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;validSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;validBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endorsements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href=&quot;/assets/eip-5453/AERC5453.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AERC5453.sol&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;reference-implementation-of-endorsableerc721&quot;&gt;Reference Implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EndorsableERC721&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Here is a reference implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EndorsableERC721&lt;/code&gt; that achieves similar behavior to &lt;a href=&quot;/EIPS/eip-4494&quot;&gt;ERC-4494&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EndorsableERC721&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC721&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AERC5453Endorsible&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//...
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_extraData&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;onlyEndorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_computeFunctionParamHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;function mint(address _to,uint256 _tokenId)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_extraData&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_mint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href=&quot;/assets/eip-5453/EndorsableERC721.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EndorsableERC721.sol&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;reference-implementation-of-thresholdmultisigforwarder&quot;&gt;Reference Implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThresholdMultiSigForwarder&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Here is a reference implementation of ThresholdMultiSigForwarder that achieves similar behavior of multi-sig threshold approval
remote contract call like a Gnosis-Safe wallet.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ThresholdMultiSigForwarder&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AERC5453Endorsible&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//...
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_gasLimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_calldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_extraData&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;onlyEndorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_computeFunctionParamHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;function forward(address _dest,uint256 _value,uint256 _gasLimit,bytes calldata _calldata)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_gasLimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_calldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_extraData&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;errorMessage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Fail to call remote contract&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_calldata&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verifyCallResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;errorMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href=&quot;/assets/eip-5453/ThresholdMultiSigForwarder.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThresholdMultiSigForwarder.sol&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;replay-attacks&quot;&gt;Replay Attacks&lt;/h3&gt;

&lt;p&gt;A replay attack is a type of attack on cryptography authentication. In a narrow sense, it usually refers to a type of attack that circumvents the cryptographically signature verification by reusing an existing signature for a message being signed again. Any implementations relying on this EIP must realize that all smart endorsements described here are cryptographic signatures that are &lt;em&gt;public&lt;/em&gt; and can be obtained by anyone. They must foresee the possibility of a replay of the transactions not only at the exact deployment of the same smart contract, but also other deployments of similar smart contracts, or of a version of the same contract on another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chainId&lt;/code&gt;, or any other similar attack surfaces. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validSince&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validBy&lt;/code&gt; fields are meant to restrict the surface of attack but might not fully eliminate the risk of all such attacks, e.g. see the &lt;a href=&quot;#phishing&quot;&gt;Phishing&lt;/a&gt; section.&lt;/p&gt;

&lt;h3 id=&quot;phishing&quot;&gt;Phishing&lt;/h3&gt;

&lt;p&gt;It’s worth pointing out a special form of replay attack by phishing. An adversary can design another smart contract in a way that the user may be tricked into signing a smart endorsement for a seemingly legitimate purpose, but the data-to-designed matches the target application&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 12 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-5453</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-5453</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Multi-privilege Management NFT Extension</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #5496 - Multi-privilege Management NFT Extension&lt;/strong&gt; is in Last Call status. It is authored by Jeremy Z (@wnft) and was originally created 2022-07-30. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-5496-multi-privilege-management-extension-for-erc-721/10427&quot;&gt;https://ethereum-magicians.org/t/eip-5496-multi-privilege-management-extension-for-erc-721/10427&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP defines an interface extending &lt;a href=&quot;/EIPS/eip-721&quot;&gt;EIP-721&lt;/a&gt; to provide shareable multi-privileges for NFTs. Privileges may be on-chain (voting rights, permission to claim an airdrop) or off-chain (a coupon for an online store, a discount at a local restaurant, access to VIP lounges in airports). Each NFT may contain many privileges, and the holder of a privilege can verifiably transfer that privilege to others. Privileges may be non-shareable or shareable. Shareable privileges can be cloned, with the provider able to adjust the details according to the spreading path. Expiration periods can also be set for each privilege.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;This standard aims to efficiently manage privileges attached to NFTs in real-time. Many NFTs have functions other than just being used as profile pictures or art collections, they may have real utilities in different scenarios. For example, a fashion store may give a discount for its own NFT holders; a DAO member NFT holder can vote for the proposal of how to use their treasury; a dApp may create an airdrop event to attract a certain group of people like some blue chip NFT holders to claim; the grocery store can issue its membership card on chain (as an NFT) and give certain privileges when the members shop at grocery stores, etc. There are cases when people who own NFTs do not necessarily want to use their privileges. By providing additional data recording different privileges a NFT collection has and interfaces to manage them, users can transfer or sell privileges without losing their ownership of the NFT.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-721&quot;&gt;EIP-721&lt;/a&gt; only records the ownership and its transfer, the privileges of an NFT are not recorded on-chain. This extension would allow merchants/projects to give out a certain privilege to a specified group of people, and owners of the privileges can manage each one of the privileges independently. This facilitates a great possibility for NFTs to have real usefulness.&lt;/p&gt;

&lt;p&gt;For example, an airline company issues a series of &lt;a href=&quot;/EIPS/eip-721&quot;&gt;EIP-721&lt;/a&gt;/&lt;a href=&quot;/EIPS/eip-1155&quot;&gt;EIP-1155&lt;/a&gt; tokens to Crypto Punk holders to give them privileges, in order to attract them to join their club. However, since these tokens are not bound to the original NFT, if the original NFT is transferred, these privileges remain in the hands of the original holders, and the new holders cannot enjoy the privileges automatically.
So, we propose a set of interfaces that can bind the privileges to the underlying NFT, while allowing users to manage the privileges independently.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.&lt;/p&gt;

&lt;p&gt;Every contract complying with this standard MUST implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC5496&lt;/code&gt; interface. The &lt;strong&gt;shareable multi-privilege extension&lt;/strong&gt; is OPTIONAL for EIP-721 contracts.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;/// @title multi-privilege extension for EIP-721
///  Note: the EIP-165 identifier for this interface is 0x076e1bbb
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5496&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;/// @notice Emitted when `owner` changes the `privilege holder` of a NFT.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrivilegeAssigned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;/// @notice Emitted when `contract owner` changes the `total privilege` of the collection
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrivilegeTotalChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTotal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldTotal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice set the privilege holder of a NFT.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @dev expires should be less than 30 days
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// Throws if `msg.sender` is not approved or owner of the tokenId.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param tokenId The NFT to set privilege for
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param privilegeId The privilege to set
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param user The privilege holder to set
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param expires For how long the privilege holder can have
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setPrivilege&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Return the expiry timestamp of a privilege
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param tokenId The identifier of the queried NFT
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param privilegeId The identifier of the queried privilege
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return Whether a user has a certain privilege
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeExpires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Check if a user has a certain privilege
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param tokenId The identifier of the queried NFT
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param privilegeId The identifier of the queried privilege
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param user The address of the queried user
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return Whether a user has a certain privilege
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasPrivilege&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Every contract implementing this standard SHOULD set a maximum privilege number before setting any privilege, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;privilegeId&lt;/code&gt; MUST NOT be greater than the maximum privilege number.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PrivilegeAssigned&lt;/code&gt; event MUST be emitted when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setPrivilege&lt;/code&gt; is called.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PrivilegeTotalChanged&lt;/code&gt; event MUST be emitted when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;total privilege&lt;/code&gt; of the collection is changed.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface&lt;/code&gt; method MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; when called with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x076e1bbb&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;/// @title Cloneable extension - Optional for EIP-721
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC721Cloneable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;/// @notice Emitted when set the `privilege ` of a NFT cloneable.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrivilegeCloned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice set a certain privilege cloneable
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param tokenId The identifier of the queried NFT
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param privilegeId The identifier of the queried privilege
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param referrer The address of the referrer
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return Whether the operation is successful or not
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clonePrivilege&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;referrer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PrivilegeCloned&lt;/code&gt; event MUST be emitted when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clonePrivilege&lt;/code&gt; is called.&lt;/p&gt;

&lt;p&gt;For Compliant contract, it is RECOMMENDED to use &lt;a href=&quot;/EIPS/eip-1271&quot;&gt;EIP-1271&lt;/a&gt; to validate the signatures.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;shareable-privileges&quot;&gt;Shareable Privileges&lt;/h3&gt;

&lt;p&gt;The number of privilege holders is limited by the number of NFTs if privileges are non-shareable. A shareable privilege means the original privilege holder can copy the privilege and give it to others, not transferring his/her own privilege to them. This mechanism greatly enhances the spread of privileges as well as the adoption of NFTs.&lt;/p&gt;

&lt;h3 id=&quot;expire-date-type&quot;&gt;Expire Date Type&lt;/h3&gt;

&lt;p&gt;The expiry timestamp of a privilege is a timestamp and stored in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt; typed variables.&lt;/p&gt;

&lt;h3 id=&quot;beneficiary-of-referrer&quot;&gt;Beneficiary of Referrer&lt;/h3&gt;

&lt;p&gt;For example, a local pizza shop offers a 30% off Coupon and the owner of the shop encourages their consumers to share the coupon with friends, then the friends can get the coupon. Let’s say Tom gets 30% off Coupon from the shop and he shares the coupon with Alice. Alice gets the coupon too and Alice’s referrer is Tom. For some certain cases, Tom may get more rewards from the shop. This will help the merchants in spreading the promotion among consumers.&lt;/p&gt;

&lt;h3 id=&quot;proposal-nft-transfer&quot;&gt;Proposal: NFT Transfer&lt;/h3&gt;

&lt;p&gt;If the owner of the NFT transfers ownership to another user, there is no impact on “privileges”. But errors may occur if the owner tries to withdraw the original &lt;a href=&quot;/EIPS/eip-721&quot;&gt;EIP-721&lt;/a&gt; token from the wrapped NFT through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unwrap()&lt;/code&gt; if any available privileges are still ongoing. We protect the rights of holders of the privileges to check the last expiration date of the privilege.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getBlockTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lastExpiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;privilege not yet expired&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ownerOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;not owner&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;_burn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;IERC721&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transferFrom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP is compatible with any kind of NFTs that follow the EIP-721 standard. It only adds more functions and data structures without interfering with the original &lt;a href=&quot;/EIPS/eip-721&quot;&gt;EIP-721&lt;/a&gt; standard.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Test cases are implemented with the reference implementation.&lt;/p&gt;

&lt;h3 id=&quot;test-code&quot;&gt;Test Code&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/assets/eip-5496/test/test.js&quot;&gt;test.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run in terminal:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;truffle &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; ./test/test.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;/assets/eip-5496/test/testCloneable.js&quot;&gt;testCloneable.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run in terminal:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;truffle &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; ./test/testCloneable.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// SPDX-License-Identifier: CC0-1.0
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;./IERC5496.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC5496&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC721&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC5496&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrivilegeRecord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrivilegeStorage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastExpiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// privId =&amp;gt; PrivilegeRecord
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrivilegeRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeTotal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// tokenId =&amp;gt; PrivilegeStorage
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrivilegeStorage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeDelegator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbol_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ERC721&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symbol_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setPrivilege&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasPrivilege&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ownerOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_isApprovedOrOwner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_isDelegatorOrHolder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ERC721: transfer caller is not owner nor approved&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;days&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;expire time invalid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeTotal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;invalid privilege id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_isApprovedOrOwner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lastExpiresAt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lastExpiresAt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrivilegeAssigned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasPrivilege&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ownerOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeExpires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_setPrivilegeTotal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrivilegeTotalChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeTotal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;privilegeTotal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getPrivilegeInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setDelegator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delegator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;privilegeDelegator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delegator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_isDelegatorOrHolder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delegator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;holder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privilegeEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delegator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;holder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isApprovedForAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;holder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delegator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;privilegeDelegator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;holder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delegator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;supportsInterface&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interfaceId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interfaceId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IERC5496&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;interfaceId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;supportsInterface&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;interfaceId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;Implementations must thoroughly consider who has the permission to set or clone privileges.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sat, 30 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-5496</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-5496</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Contracts Dependencies Registry</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #6224 - Contracts Dependencies Registry&lt;/strong&gt; is in Last Call status. It is authored by Artem Chystiakov (@arvolear) and was originally created 2022-12-27. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-6224-contracts-dependencies-registry/12316&quot;&gt;https://ethereum-magicians.org/t/eip-6224-contracts-dependencies-registry/12316&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP introduces an on-chain registry system that a decentralized protocol may use to manage its smart contracts.&lt;/p&gt;

&lt;p&gt;The proposed system consists of two components: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependant&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; contract stores references to every smart contract used within a protocol, optionally making them upgradeable by deploying self-managed proxies on top, and acts as a hub the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependant&lt;/code&gt; contracts query to fetch their required dependencies from.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;In the ever-growing Ethereum ecosystem, projects tend to become more and more complex. Modern protocols require portability and agility to satisfy customer needs by continuously delivering new features and staying on pace with the industry. However, the requirement is hard to achieve due to the immutable nature of blockchains and smart contracts. Moreover, the increased complexity and continuous delivery bring bugs and entangle the dependencies between the contracts, making systems less supportable.&lt;/p&gt;

&lt;p&gt;Applications that have a clear architectural facade; which are designed with forward compatibility in mind; which dependencies are transparent and clean are easier to develop and maintain. The given EIP tries to solve the aforementioned problems by presenting two smart contracts: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependant&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The advantages of using the provided system might be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Structured smart contracts management via specialized contracts.&lt;/li&gt;
  &lt;li&gt;Ad-hoc upgradeability provision of a protocol.&lt;/li&gt;
  &lt;li&gt;Runtime addition, removal, and substitution of smart contracts.&lt;/li&gt;
  &lt;li&gt;Dependency injection mechanism to keep smart contracts’ dependencies under control.&lt;/li&gt;
  &lt;li&gt;Ability to specify custom access control rules to maintain the protocol.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.&lt;/p&gt;

&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;

&lt;p&gt;The system consists of two smart contracts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; that is a singleton registry to manage and upgrade a protocol’s smart contracts.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependant&lt;/code&gt; that is a mix-in which enables a dependency injection mechanism.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following diagram depicts the relationship between the registry and its dependants:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/eip-6224/diagram.svg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;contractsregistry&quot;&gt;ContractsRegistry&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; is the main contract of the proposed system. It MUST store the references to every standalone contract used within a protocol. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractRegistry&lt;/code&gt; MAY be configured to deploy a proxy contract of choice on top of the registered contracts.&lt;/p&gt;

&lt;p&gt;Additionally, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; MUST reject the registration of zero addresses.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; MUST implement the following interface:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IContractsRegistry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The event that is emitted when the contract gets added to the registry
     * @param name the name of the contract
     * @param contractAddress the address of the added contract
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ContractAdded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The event that is emitted when the proxy contract gets added to the registry
     * @param name the name of the contract
     * @param contractAddress the address of the proxy contract
     * @param implementation the address of the implementation contract
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyContractAdded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;implementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The event that is emitted when the proxy contract gets upgraded through the registry
     * @param name the name of the contract
     * @param newImplementation the address of the new implementation contract
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyContractUpgraded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The event that is emitted when the contract gets removed from the registry
     * @param name the name of the removed contract
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ContractRemoved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that returns an associated contract by the name. 
     *
     * MUST revert if the requested contract is `address(0)`
     *
     * @param name the name of the contract
     * @return the address of the contract
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that checks if a contract with a given name has been added
     * @param name the name of the contract
     * @return true if the contract is present in the registry
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that injects dependencies into the given contract.
     *
     * MUST call the `setDependencies()` with `address(this)` and `bytes(&quot;&quot;)` as arguments on the provided contract
     *
     * @param name the name of the contract
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injectDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that injects dependencies into the given contract with extra data.
     *
     * MUST call the `setDependencies()` with `address(this)` and `data` as arguments on the provided contract
     *
     * @param name the name of the contract
     * @param data the extra context data that will be passed to the dependant contract
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injectDependenciesWithData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that upgrades added proxy contract with a new implementation.
     *
     * It is the Owner&apos;s responsibility to ensure the compatibility between implementations.
     *
     * MUST emit `ProxyContractUpgraded` event
     *
     * @param name the name of the proxy contract
     * @param newImplementation the new implementation the proxy will be upgraded to
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgradeContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that upgrades added proxy contract with a new implementation, providing data
     *
     * It is the Owner&apos;s responsibility to ensure the compatibility between implementations.
     *
     * MUST emit `ProxyContractUpgraded` event
     *
     * @param name the name of the proxy contract
     * @param newImplementation the new implementation the proxy will be upgraded to
     * @param data the data that the proxy will be called with after upgrade. This can be an ABI encoded function call
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgradeContractAndCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that adds pure (non-proxy) contracts to the `ContractsRegistry`. The contracts MAY either be
     * the ones the system does not have direct upgradeability control over or those that are not upgradeable by design.
     *
     * MUST emit `ContractAdded` event. Reverts if the provided address is `address(0)`
     *
     * @param name the name to associate the contract with
     * @param contractAddress the address of the contract to be added
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that adds the proxy contracts to the registry by deploying them above the provided implementation.
     *
     * The function may be used to add a contract that the `ContractsRegistry` has to be able to upgrade.
     *
     * MUST emit `ProxyContractAdded` event. Reverts if implementation address is `address(0)`
     *
     * @param name the name to associate the contract with
     * @param contractAddress the address of the implementation to point the proxy to
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addProxyContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that adds the proxy contracts to the registry by deploying them above the provided implementation,
     * providing data.
     *
     * The function may be used to add a contract that the `ContractsRegistry` has to be able to upgrade.
     *
     * MUST emit `ProxyContractAdded` event. Reverts if implementation address is `address(0)`
     *
     * @param name the name to associate the contract with
     * @param contractAddress the address of the implementation
     * @param data the data that the proxy will be called with. This can be an ABI encoded initialization call
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addProxyContractAndCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that adds an already deployed proxy to the `ContractsRegistry`. It MAY be used
     * when the system migrates to the new `ContractRegistry`. In that case, the new registry MUST have the
     * credentials to upgrade the newly added proxies.
     *
     * MUST emit `ProxyContractAdded` event. Reverts if implementation address is `address(0)`
     *
     * @param name the name to associate the contract with
     * @param contractAddress the address of the proxy
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;justAddProxyContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function to remove contracts from the ContractsRegistry.
     *
     * MUST emit `ContractRemoved` event. Reverts if the contract is already removed
     *
     * @param name the associated name with the contract
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;removeContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;dependant&quot;&gt;Dependant&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; works together with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependant&lt;/code&gt; contract. Every standalone contract of a protocol MUST inherit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependant&lt;/code&gt; in order to support the dependency injection mechanism.&lt;/p&gt;

&lt;p&gt;The required dependencies MUST be set in the overridden &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setDependencies&lt;/code&gt; method, not in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;constructor&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initializer&lt;/code&gt; methods.&lt;/p&gt;

&lt;p&gt;Only the injector MUST be able to call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setDependencies&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setInjector&lt;/code&gt; methods. The initial injector will be a zero address, in that case, the call MUST NOT revert on access control checks.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependant&lt;/code&gt; contract MUST implement the following interface:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDependant&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that is called from the `ContractsRegistry` to inject dependencies.
     *
     * The contract MUST perform a proper access check of `msg.sender`. The calls should only be possible from `ContractsRegistry`
     *
     * @param contractsRegistry the registry to pull dependencies from
     * @param data the extra data that might provide additional application-specific context
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractsRegistry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that sets the new dependency injector.
     *
     * The contract MUST perform a proper access check of `msg.sender`
     *
     * @param injector the new dependency injector
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice The function that gets the current dependency injector
     * @return the current dependency injector
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependant&lt;/code&gt; contract MAY store the dependency injector (usually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt;) address in the special slot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x3d1f25f1ac447e55e7fec744471c4dab1c6a2b6ffb897825f9ea3d2e8c9be583&lt;/code&gt; (obtained as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(uint256(keccak256(&quot;eip6224.dependant.slot&quot;)) - 1)&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;There are a few design decisions that have to be explicitly specified:&lt;/p&gt;

&lt;h3 id=&quot;contractsregistry-rationale&quot;&gt;ContractsRegistry Rationale&lt;/h3&gt;

&lt;h4 id=&quot;contracts-identifier&quot;&gt;Contracts Identifier&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt; contracts identifier is chosen over the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; to maintain code readability and reduce the human error chances when interacting with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt;. Being the topmost smart contract of a protocol, it MAY be typical for the users to interact with it via block explorers or DAOs. Clarity was prioritized over gas usage.&lt;/p&gt;

&lt;p&gt;Due to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt; identifier, the event parameters are not indexed. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string indexed&lt;/code&gt; parameter will become the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; hash of the contract name if it is larger than 32 bytes. This fact reduces readability, which was prioritized.&lt;/p&gt;

&lt;h4 id=&quot;reverts&quot;&gt;Reverts&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getContract&lt;/code&gt; view function reverts if the requested contract is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address(0)&lt;/code&gt;. This is essential to minimize the risks of misinitialization of a protocol. Correct contracts SHOULD be added to the registry prior to any dependency injection actions.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addContract&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addProxyContract&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addProxyContractAndCall&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;justAddProxyContract&lt;/code&gt; methods revert if the provided address is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address(0)&lt;/code&gt; for the same risk minimization reason.&lt;/p&gt;

&lt;h3 id=&quot;dependant-rationale&quot;&gt;Dependant Rationale&lt;/h3&gt;

&lt;h4 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; parameter is provided to carry additional application-specific context. It MAY be used to extend the method’s behavior.&lt;/p&gt;

&lt;h4 id=&quot;injector&quot;&gt;Injector&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setInjector&lt;/code&gt; function is made &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;external&lt;/code&gt; to support the dependency injection mechanism for factory-made contracts. However, the method SHOULD be used with extra care.&lt;/p&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note that the reference implementation depends on OpenZeppelin contracts &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4.9.2&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;contractsregistry-implementation&quot;&gt;ContractsRegistry Implementation&lt;/h3&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@openzeppelin/contracts/utils/Address.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TransparentUpgradeableProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OwnableUpgradeable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Dependant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;./Dependant.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IContractsRegistry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ContractAdded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyContractAdded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;implementation&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyContractUpgraded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ContractRemoved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injectDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injectDependenciesWithData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgradeContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgradeContractAndCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addProxyContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addProxyContractAndCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;justAddProxyContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;removeContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyUpgrader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;immutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_OWNER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;modifier&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_onlyOwner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_OWNER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;what_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;TransparentUpgradeableProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;what_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upgradeToAndCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;TransparentUpgradeableProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;what_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upgradeTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getImplementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;what_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// bytes4(keccak256(&quot;implementation()&quot;)) == 0x5c60da1b
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;success_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndata_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;what_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;staticcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;hex&quot;5c60da1b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;success_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ProxyUpgrader: not a proxy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returndata_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_onlyOwner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_OWNER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ProxyUpgrader: not an owner&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ContractsRegistry&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IContractsRegistry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OwnableUpgradeable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ProxyUpgrader&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_proxyUpgrader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_isProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__ContractsRegistry_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initializer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_proxyUpgrader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyUpgrader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;__Ownable_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;ContractsRegistry: this mapping doesn&apos;t exist&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getProxyUpgrader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_proxyUpgrader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injectDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;injectDependenciesWithData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injectDependenciesWithData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;ContractsRegistry: this mapping doesn&apos;t exist&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;Dependant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dependant_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dependant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dependant_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgradeContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;upgradeContractAndCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgradeContractAndCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractToUpgrade_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;contractToUpgrade_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;ContractsRegistry: this mapping doesn&apos;t exist&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_isProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contractToUpgrade_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;ContractsRegistry: not a proxy contract&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;_proxyUpgrader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contractToUpgrade_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyContractUpgraded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newImplementation_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;ContractsRegistry: zero address is forbidden&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ContractAdded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addProxyContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;addProxyContractAndCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addProxyContractAndCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;ContractsRegistry: zero address is forbidden&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proxyAddr_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_deployProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_proxyUpgrader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proxyAddr_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_isProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxyAddr_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyContractAdded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proxyAddr_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;justAddProxyContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;ContractsRegistry: zero address is forbidden&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_isProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyContractAdded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_proxyUpgrader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getImplementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;removeContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onlyOwner&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;ContractsRegistry: this mapping doesn&apos;t exist&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_isProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contracts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ContractRemoved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_deployProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;admin_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransparentUpgradeableProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contractAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;admin_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;dependant-implementation&quot;&gt;Dependant Implementation&lt;/h3&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDependant&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractsRegistry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dependant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDependant&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @dev bytes32(uint256(keccak256(&quot;eip6224.dependant.slot&quot;)) - 1)
     */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_INJECTOR_SLOT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;mh&quot;&gt;0x3d1f25f1ac447e55e7fec744471c4dab1c6a2b6ffb897825f9ea3d2e8c9be583&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;modifier&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dependant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_checkInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_setInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contractsRegistry_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injector_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_checkInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_setInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;injector_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injector_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slot_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_INJECTOR_SLOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;injector_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_setInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injector_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slot_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_INJECTOR_SLOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sstore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injector_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_checkInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injector_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getInjector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;injector_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;injector_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Dependant: not an injector&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;It is crucial for the owner of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; to keep their keys in a safe place. The loss/leakage of credentials to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; will lead to the application’s point of no return. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractRegistry&lt;/code&gt; is a cornerstone of a protocol, access must be granted to the trusted parties only.&lt;/p&gt;

&lt;h3 id=&quot;contractsregistry-security&quot;&gt;ContractsRegistry Security&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContractsRegistry&lt;/code&gt; does not perform any upgradeability checks between the proxy upgrades. It is the user’s responsibility to make sure that the new implementation is compatible with the old one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;dependant-security&quot;&gt;Dependant Security&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependant&lt;/code&gt; contract MUST set its dependency injector no later than the first call to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setDependencies&lt;/code&gt; function is made. That being said, it is possible to front-run the first dependency injection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Tue, 27 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-6224</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-6224</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Single-contract Multi-delegatecall</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #6357 - Single-contract Multi-delegatecall&lt;/strong&gt; is in Last Call status. It is authored by Gavin John (@Pandapip1) and was originally created 2023-01-18. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-6357-single-contract-multicall/12621&quot;&gt;https://ethereum-magicians.org/t/eip-6357-single-contract-multicall/12621&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP standardizes an interface containing a single function, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;multicall&lt;/code&gt;, allowing EOAs to call multiple functions of a smart contract in a single transaction, and revert all calls if any call fails.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Currently, in order to transfer several &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt; NFTs, one needs to submit a number of transactions equal to the number of NFTs being tranferred. This wastes users’ funds by requiring them to pay 21000 gas fee for every NFT they transfer.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.&lt;/p&gt;

&lt;p&gt;Contracts implementing this EIP must implement the following interface:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMulticall&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;/// @notice           Takes an array of abi-encoded call data, delegatecalls itself with each calldata, and returns the abi-encoded result
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @dev              Reverts if any delegatecall reverts
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param    data    The abi-encoded data
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @returns  results The abi-encoded return values
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;multicall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice           OPTIONAL. Takes an array of abi-encoded call data, delegatecalls itself with each calldata, and returns the abi-encoded result
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @dev              Reverts if any delegatecall reverts
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param    data    The abi-encoded data
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param    values  The effective msg.values. These must add up to at most msg.value
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @returns  results The abi-encoded return values
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;multicallPayable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;multicallPayable&lt;/code&gt; is optional because it isn’t always feasible to implement, due to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.value&lt;/code&gt; splitting.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This is compatible with most existing multicall functions.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;The following JavaScript code, using the Ethers library, should atomically transfer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amt&lt;/code&gt; units of an &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; token to both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addressA&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addressB&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;multicall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encodeFunctionData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;transfer&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;addressA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;amt&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encodeFunctionData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;transfer&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;addressB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;amt&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;/// Derived from OpenZeppelin&apos;s implementation
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Multicall&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMulticall&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;multicall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;delegatecall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;multicallPayable&lt;/code&gt; should only be used if the contract is able to support it. A naive attempt at implementing it could allow an attacker to call a payable function multiple times with the same ether.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Wed, 18 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-6357</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-6357</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Empty accounts deprecation</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7523 - Empty accounts deprecation&lt;/strong&gt; is in Last Call status. It is authored by Peter Davies (@petertdavies) and was originally created 2023-09-19. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7523-empty-accounts-deprecation/15870&quot;&gt;https://ethereum-magicians.org/t/eip-7523-empty-accounts-deprecation/15870&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP prohibits the state of any post-merge network from containing empty accounts. Since no empty accounts exist outside the testsuite and no new ones can be created this requirement is already achieved in practice. An explicit ban reduces technical debt going forward.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;The possibility of empty accounts is a historical artifact of the early history of Ethereum. The only networks that have ever been capable of containing them are Ethereum Mainnet, the deprecated testnet Ropsten, Etheruem Classic Mainnet and various Ethereum Classic testnets. All remaining empty accounts on Mainnet were cleared in block &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;14049881&lt;/code&gt; (transaction &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xf955834bfa097458a9cf6b719705a443d32e7f43f20b9b0294098c205b4bcc3d&lt;/code&gt;) and a similar transaction was sent on Ethereum Classic. None of the other myriad EVM-compatible networks are old enough to have empty accounts and there is no realistic prospect that anyone will encounter an empty account in a production context.&lt;/p&gt;

&lt;p&gt;Despite empty accounts no longer existing, they still impose a legacy of technical debt. &lt;a href=&quot;/EIPS/eip-161&quot;&gt;EIP-161&lt;/a&gt; imposes complicated rules that require a client to delete an empty account when it is “touched”. As the Ethereum specification continues to evolve new edgecases of the “touch” rules arise which must be debated, implemented, tested and documented. If a future client wishes to only support post-merge blocks it must implement unnecessary empty account support solely to pass the test suite.&lt;/p&gt;

&lt;p&gt;By prohibiting empty accounts on post-merge networks, this EIP frees designers and implementers of Ethereum and related blockchains from the burden of having to consider them going forward.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.&lt;/p&gt;

&lt;p&gt;An empty account is an account with has &lt;strong&gt;no code&lt;/strong&gt; and &lt;strong&gt;zero nonce&lt;/strong&gt; and &lt;strong&gt;zero balance&lt;/strong&gt;. This is the same as the definition in &lt;a href=&quot;/EIPS/eip-161&quot;&gt;EIP-161&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On networks that undergo the merge transition, the pre state of the merge block may not contain any empty accounts. For networks that are merged at genesis, none of the genesis accounts may be empty accounts.&lt;/p&gt;

&lt;p&gt;Rather than performing a scan of the state, clients MAY assume the following chains have no post-merge empty accounts:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The Mainnet chain whose merge block has hash &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x56a9bb0302da44b8c0b3df540781424684c3af04d0b7a38d72842b762076a664&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Any chain which satisfies all of the following:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;has no empty accounts in the genesis.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;had a post Spurious Dragon fork at genesis.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Ethereum specification is declared to be undefined in the presence of an empty account in a post-merge context. Any testcase involving post-merge empty accounts is invalid.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;This EIP was drafted to be the simplest possible way of eliminating the long term technical debt imposed by empty accounts. The Merge was chosen as a natural easily identifiable cutoff point.&lt;/p&gt;

&lt;p&gt;Alternative approaches include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Using an earlier cutoff point, such as block &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;14049881&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Identifying a wider range of edge case behaviour that never happened.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These approaches were rejected as being unnecessarily complicated.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;As EIP does not change any behaviour that can occur outside the testsuite, it has no backwards compatibility consequences.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;The validity of this EIP is dependent on the assertion that all empty accounts on Ethereum Mainnet were cleared prior to the merge. This should be subject to appropriate verification.&lt;/p&gt;

&lt;p&gt;Any networks artificially created with empty accounts will cause problems with tooling and clients.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Tue, 19 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7523</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7523</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Revert creation in case of non-empty storage</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7610 - Revert creation in case of non-empty storage&lt;/strong&gt; is in Last Call status. It is authored by Gary Rong (@rjl493456442), Martin Holst Swende (@holiman) and was originally created 2024-02-02. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-revert-creation-in-case-of-non-empty-storage/18452&quot;&gt;https://ethereum-magicians.org/t/eip-revert-creation-in-case-of-non-empty-storage/18452&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP causes contract creation to throw an error when attempted at an address with pre-existing storage.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.&lt;/p&gt;

&lt;p&gt;If a contract creation is attempted due to a creation transaction, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt; opcode, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; opcode, or any other reason, and the destination address already has either a nonzero nonce, a nonzero code length, or non-empty storage, then the creation MUST throw as if the first byte in the init code were an invalid opcode. This change MUST apply retroactively for all existing blocks.&lt;/p&gt;

&lt;p&gt;This EIP amends &lt;a href=&quot;/EIPS/eip-684&quot;&gt;EIP-684&lt;/a&gt; with one extra condition, requiring empty storage for contract deployment.&lt;/p&gt;

&lt;p&gt;This EIP will not affect &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt;, since the authority’s nonce is always incremented after an authorization is applied, which conflicts with the condition required for contract deployment.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;EIP-684 defines two conditions for contract deployment: the destination address must have zero nonce and zero code length. Unfortunately, this is not sufficient. Before &lt;a href=&quot;/EIPS/eip-161&quot;&gt;EIP-161&lt;/a&gt; was applied, the nonce of a newly deployed contract remained set to zero. Therefore, it was entirely possible to create a contract with a zero nonce and zero code length but with non-empty storage, if slots were set in the constructor. There exists 28 such contracts on Ethereum mainnet at this time.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This is an execution layer upgrade, and so it requires a hard fork.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;There exists quite a number of tests in the ethereum tests repo as well as in the execution spec tests, which test the scenario of deployment to targets with non-empty storage. These tests have been considered problematic in the past; Reth and EELS both intentionally implement a version of the account reset solely to pass the tests. Py-evm declared the situation impossible and never implemented account reset.&lt;/p&gt;

&lt;p&gt;Refilling the existing tests will provide sufficient coverage for this EIP.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;This EIP is a security upgrade: it enforces the immutability of deployed code.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 02 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7610</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7610</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>ETH transfers emit a log</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7708 - ETH transfers emit a log&lt;/strong&gt; is in Last Call status. It is authored by Vitalik Buterin (@vbuterin), Peter Davies (@petertdavies), Etan Kissling (@etan-status), Gajinder Singh (@g11tech), Carson (@carsons-eels), Jared Wasinger (@jwasinger) and was originally created 2024-05-17. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7708-eth-transfers-emit-a-log/20034&quot;&gt;https://ethereum-magicians.org/t/eip-7708-eth-transfers-emit-a-log/20034&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;All ETH transfers emit a log.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Logs are often used to track when balance changes of assets on Ethereum. Logs work for &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; tokens, but they do not work for ETH. ETH transfers from EOAs can be read from the transaction list in the block, but ETH transfers from smart contract wallets are not automatically logged anywhere. This has already led to problems in the past, eg. early exchanges would often not properly support deposits from smart contract wallets, or only support them with a much longer delay. This EIP proposes that we automatically generate a log every time a value-transferring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; happens. We also add a similar log for transfers in transactions, so that all ETH transfers can be tracked using one mechanism.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;eth-transfer-logs&quot;&gt;ETH transfer logs&lt;/h3&gt;

&lt;p&gt;A log, identical to a LOG3, is issued for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Any nonzero-value-transferring transaction to a different account, before any other logs created by EVM execution&lt;/li&gt;
  &lt;li&gt;Any nonzero-value-transferring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; to a different account, at the time that the value transfer executes&lt;/li&gt;
  &lt;li&gt;Any nonzero-value-transferring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; to a different account, at the time that the value transfer executes&lt;/li&gt;
  &lt;li&gt;Any nonzero-value-transferring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; to the created account, at the time that the value transfer executes&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Field&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address&lt;/code&gt; emitting log&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xfffffffffffffffffffffffffffffffffffffffe&lt;/code&gt; (&lt;a href=&quot;/EIPS/eip-4788&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSTEM_ADDRESS&lt;/code&gt;&lt;/a&gt;)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;topics[0]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(&apos;Transfer(address,address,uint256)&apos;)&lt;/code&gt;)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;topics[1]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt; address (zero prefixed to fill uint256)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;topics[2]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to&lt;/code&gt; address (zero prefixed to fill uint256)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount&lt;/code&gt; in Wei (big endian uint256)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;This matches the &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; Transfer event definition.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;This is the simplest possible implementation that ensures that all ETH transfers are implemented in some kind of record that can be easily accessed through making RPC calls into a node, or through asking for a Merkle branch that is hashed into the block root. The log type is compatible with the ERC-20 token standard, but does not introduce any overly-specific ERC-20 features (eg. ABI encodings) into the specification.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSTEM_ADDRESS&lt;/code&gt; is reused as the log emitter for consistency with other protocol-originated operations (e.g. &lt;a href=&quot;/EIPS/eip-4788&quot;&gt;EIP-4788&lt;/a&gt;) and to distinguish these protocol-generated logs from logs emitted by user contracts.&lt;/p&gt;

&lt;p&gt;Fee payment logs for priority fees paid to the coinbase were considered. However, they are a distinct category from transfers, and adding these logs to this EIP would explode the log volume in a way that raises the intrinsic cost of transfer logs (and therefore transactions), putting an unreasonable load on the network. Clients can already compute these fee amounts from the block header and transaction receipt, so it is unnecessary to log them. The base fee burn is excluded for the same reason: the burned amount is already derivable from the block header.&lt;/p&gt;

&lt;p&gt;Withdrawals were also considered, but they are not attached to a transaction, which means there is no natural emission point. Additionally, they are already easily derivable from block information. Adding these kinds of logs would duplicate data already available to clients.&lt;/p&gt;

&lt;p&gt;Clients who wish to provide a unified view for consumers MAY expose a new aggregating RPC.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;h3 id=&quot;eth-burns-via-selfdestruct&quot;&gt;ETH burns via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;After &lt;a href=&quot;/EIPS/eip-8246&quot;&gt;EIP-8246&lt;/a&gt;, ETH can no longer be burned via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; to self or by sending ETH to an account marked for selfdestruction. Therefore, this EIP does not specify this edge-case.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Transfer log emission for plain transactions, EOAs, delegated EOAs, and across all transaction types&lt;/li&gt;
  &lt;li&gt;Transfer logs across the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; family and how the executing context attributes the sender&lt;/li&gt;
  &lt;li&gt;Transfer logs for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; endowments, initcode behavior, and failure modes&lt;/li&gt;
  &lt;li&gt;Transfer logs for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; to self vs. a different beneficiary, including pre-existing and cross-tx contracts&lt;/li&gt;
  &lt;li&gt;Log ordering: Transfer logs appear before any EVM-emitted logs in a transaction, and nested-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; Transfer logs appear in chronological call order&lt;/li&gt;
  &lt;li&gt;Negative cases where no log is emitted (zero-value, reverts, rolled-back inner calls, fee payments)&lt;/li&gt;
  &lt;li&gt;Transfers to special-purpose addresses (precompiles, the system address, the coinbase)&lt;/li&gt;
  &lt;li&gt;Fork transition behavior at the EIP-7708 activation boundary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Test cases for this EIP can be found in the Execution Layer Specification suite &lt;a href=&quot;https://github.com/ethereum/execution-specs/tree/155c3e136d81dcd5c61086c9d832595b7641db4a/tests/amsterdam/eip7708_eth_transfer_logs&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eip7708_eth_transfer_logs&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;ETH transfers already cost a minimum of 6700 gas, which is much more expensive than the LOG3 opcode (1500 gas). Hence, this EIP does not increase the worst-case number of logs that can be put into a block. It will somewhat increase the average number of logs.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 17 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7708</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7708</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Network Upgrade Inclusion Stages</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7723 - Network Upgrade Inclusion Stages&lt;/strong&gt; is in Last Call status. It is authored by Tim Beiko (@timbeiko), Alex Stokes (@ralexstokes), Ansgar Dietrichs (@adietrichs), Nixo (@nixorokish), Parithosh Jayanthi (@parithosh) and was originally created 2024-06-12. It is in the  category of type Meta. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7723-network-upgrade-inclusion-stages/20281&quot;&gt;https://ethereum-magicians.org/t/eip-7723-network-upgrade-inclusion-stages/20281&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;Defines the stages that EIPs go through in the process of planning network upgrades: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;This EIP proposes definitions for the various stages EIPs go through when planning network upgrades. It also provides context and guidelines around when and how EIPs should be moved from one stage to the next.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.&lt;/p&gt;

&lt;p&gt;All EIP stages apply to a single network upgrade. EIPs must be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled&lt;/code&gt; separately for each network upgrade. While an EIP cannot be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included&lt;/code&gt; in two network upgrades, an EIP being &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; in a previous upgrade does not prevent it from being &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled&lt;/code&gt; for inclusion in any future upgrade.&lt;/p&gt;

&lt;p&gt;The stages below are generally defined for Standards Track - Core EIPs, which must be activated synchronously by all nodes on a network. To help with prioritization and communications, non-Core EIPs may also be assigned these stages. The differences in the process and implications for non-Core EIPs are noted in each stage’s definition.&lt;/p&gt;

&lt;h3 id=&quot;upgrade-meta-eips&quot;&gt;Upgrade Meta EIPs&lt;/h3&gt;

&lt;p&gt;Anyone &lt;strong&gt;MAY&lt;/strong&gt; draft a Meta EIP to list EIPs for a network upgrade. This Meta EIP &lt;strong&gt;SHOULD&lt;/strong&gt; include four categories in its specification section: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt;. Even if a category is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TBD&lt;/code&gt;, it &lt;strong&gt;SHOULD&lt;/strong&gt; be included in the initial draft for clarity.&lt;/p&gt;

&lt;p&gt;When the Upgrade Meta EIP is moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Review&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed for Inclusion&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; list &lt;strong&gt;SHOULD&lt;/strong&gt; be removed. When it is moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Last Call&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; lists &lt;strong&gt;SHOULD&lt;/strong&gt; be removed, leaving only the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; list.&lt;/p&gt;

&lt;p&gt;Before the Upgrade Meta EIP is moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Final&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; stage &lt;strong&gt;MUST&lt;/strong&gt; be renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included&lt;/code&gt; and contain only EIPs that were activated with the upgrade.&lt;/p&gt;

&lt;h3 id=&quot;upgrade-devnets&quot;&gt;Upgrade Devnets&lt;/h3&gt;

&lt;p&gt;When preparing a network upgrade, client developers typically implement EIPs first on an ephemeral test network (upgrade devnet) to verify client interoperability before deploying to long-lived test networks. These upgrade devnets follow a naming convention of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeName-devnet-version&lt;/code&gt; (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pectra-devnet-0&lt;/code&gt; for the first upgrade devnet of the Pectra network upgrade, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dencun-devnet-1&lt;/code&gt; for the second upgrade devnet of the Dencun update, etc).&lt;/p&gt;

&lt;p&gt;Since client developers’ ability to include EIPs in a network upgrade is constrained by what can be implemented and tested in these upgrade devnets, the &lt;a href=&quot;#considered-for-inclusion&quot;&gt;Considered for Inclusion&lt;/a&gt; and &lt;a href=&quot;#scheduled-for-inclusion&quot;&gt;Scheduled for Inclusion&lt;/a&gt; sections below propose aligning these statuses with EIPs’ implementation status in upgrade devnets.&lt;/p&gt;

&lt;h3 id=&quot;proposed-for-inclusion&quot;&gt;Proposed for Inclusion&lt;/h3&gt;

&lt;p&gt;To propose an EIP for inclusion, someone &lt;strong&gt;MUST&lt;/strong&gt; open a pull request to add it to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed for Inclusion&lt;/code&gt; (PFI) section of the Upgrade Meta EIP. The proposer of an EIP &lt;strong&gt;SHOULD&lt;/strong&gt; serve as the primary point of contact for that EIP for the duration of the upgrade cycle or &lt;strong&gt;SHOULD&lt;/strong&gt; designate another person to serve in that role. Reasonable pull requests &lt;strong&gt;SHOULD&lt;/strong&gt; be merged in a timely fashion by the Upgrade Meta EIP author.&lt;/p&gt;

&lt;p&gt;At this stage, implementation teams &lt;strong&gt;SHOULD&lt;/strong&gt; review the EIP. For Core EIPs, this should be in the context of including it in the said upgrade. For non-Core EIPs, this should be in the context of supporting Core EIPs before the network upgrade is activated.&lt;/p&gt;

&lt;p&gt;Note that EIPs must be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed for Inclusion&lt;/code&gt; for each network upgrade. In other words, proposals do not “carry over” to the next upgrade if an EIP is not included in the one it was first proposed for.&lt;/p&gt;

&lt;h3 id=&quot;considered-for-inclusion&quot;&gt;Considered for Inclusion&lt;/h3&gt;

&lt;p&gt;Once client developers have reviewed an EIP which was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed for Inclusion&lt;/code&gt;, they &lt;strong&gt;MAY&lt;/strong&gt; move it to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; (CFI) stage. Once a decision is made by client teams to move an EIP to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt;, the Upgrade Meta EIP &lt;strong&gt;SHOULD&lt;/strong&gt; be updated to reflect this.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; signals that client developers intend to attempt to include the EIP in devnets. The All Core Devs Execution (ACDE) and Consensus (ACDC) call facilitators should work with the testing teams to propose a priority ordering of CFI EIPs to be reviewed by client developers, and then reflect this prioritization in the Meta EIP. This prioritization should inform which EIPs should be included in upcoming devnets, with some flexibility if circumstances change.&lt;/p&gt;

&lt;p&gt;Assuming it meets all the requirements for mainnet deployment it &lt;strong&gt;MAY&lt;/strong&gt; be included in the network upgrade. This stage is similar to “concept ACK” in other open source projects, and is not sufficient to result in deployment to mainnet.&lt;/p&gt;

&lt;p&gt;Non-Core EIPs that are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; &lt;strong&gt;SHOULD&lt;/strong&gt; be supported prior to the network upgrade being activated.&lt;/p&gt;

&lt;p&gt;An EIP &lt;strong&gt;MAY&lt;/strong&gt; be moved from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; if client teams are against including the EIP in the network upgrade.&lt;/p&gt;

&lt;p&gt;An EIP &lt;strong&gt;SHOULD&lt;/strong&gt; have a Python implementation accompanied by tests in &lt;a href=&quot;https://github.com/ethereum/execution-specs/blob/78fb726158c69d8fa164e28f195fabf6ab59b915/README.md&quot;&gt;execution-specs&lt;/a&gt; submitted as an open PR. The EIP writer is encouraged to reach out to the maintainers of execution-specs for assistance with implementation. Client developers &lt;strong&gt;MAY&lt;/strong&gt; decide to allow an EIP to be moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; without either implementation, being aware that the absence of these implementations could lead to delays in the testing cycle.&lt;/p&gt;

&lt;p&gt;Any updates to an EIP that is already at this stage &lt;strong&gt;SHOULD&lt;/strong&gt; be accompanied by the appropriate updates to its implementation and tests in &lt;a href=&quot;https://github.com/ethereum/execution-specs/blob/78fb726158c69d8fa164e28f195fabf6ab59b915/README.md&quot;&gt;execution-specs&lt;/a&gt; if deemed necessary by client developers.&lt;/p&gt;

&lt;h3 id=&quot;declined-for-inclusion&quot;&gt;Declined for Inclusion&lt;/h3&gt;

&lt;p&gt;At any time during the network upgrade planning process, client developers &lt;strong&gt;MAY&lt;/strong&gt; move EIPs from any other stage to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; (DFI) stage if client teams are against including the EIP in the network upgrade. Once a decision is made by client teams to move an EIP to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt;, the Upgrade Meta EIP &lt;strong&gt;SHOULD&lt;/strong&gt; be updated to reflect this.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; signals that client developers wish to exclude the EIP from the current network upgrade and stop discussing its potential inclusion or implementation status in relation to this upgrade. An EIP which was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; in a particular upgrade &lt;strong&gt;MAY&lt;/strong&gt; still be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed for Inclusion&lt;/code&gt; in a subsequent upgrade. In exceptional circumstances, client developers &lt;strong&gt;MAY&lt;/strong&gt; choose to move an EIP from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;scheduled-for-inclusion&quot;&gt;Scheduled for Inclusion&lt;/h3&gt;

&lt;p&gt;An EIP can be moved to Scheduled for Inclusion (SFI) when core developers:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Agree upon a strong intent to include the EIP in the next network upgrade.&lt;/li&gt;
  &lt;li&gt;Agree that an EIP’s specifications and implementations have reached a certain level of maturity.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I.e., an SFI status signals that the EIP is on track for inclusion barring unforeseen issues.&lt;/p&gt;

&lt;p&gt;The following critieria can be applied to ascertain whether an EIP is mature (stable) enough to move to SFI:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It has been included in a devnet that has demonstrated stability (e.g., high participation, no critical bugs for ≥1 week).&lt;/li&gt;
  &lt;li&gt;The EIP specification is close to final (no placeholder values or pending design decisions).&lt;/li&gt;
  &lt;li&gt;It has minimal interactions with other CFI EIPs, OR those interactions have been tested in the same devnet.&lt;/li&gt;
  &lt;li&gt;Testing coverage is adequate (clients pass consensus tests, no known divergence across clients).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All Core Devs Testing (ACDT) calls may review EIPs to determine SFI eligibility. Status changes will then be ratified on ACDE or ACDC before assigning SFI status.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; signals that the EIP is on track for inclusion barring unforeseen issues. EIPs with incomplete specs or untested interactions should remain CFI until these conditions are met. The latest Upgrade Devnet must contain all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; Core EIPs.&lt;/p&gt;

&lt;p&gt;An EIP &lt;strong&gt;MAY&lt;/strong&gt; be moved from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; if circumstances necessitate removal, as agreed by client teams. An EIP &lt;strong&gt;MAY&lt;/strong&gt; also be moved from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; if client teams remain in favor of including the EIP in the network upgrade but cannot commit to including it in the &lt;strong&gt;next&lt;/strong&gt; Upgrade Devnet.&lt;/p&gt;

&lt;p&gt;An EIP &lt;strong&gt;MUST&lt;/strong&gt; have a Python implementation accompanied by tests in &lt;a href=&quot;https://github.com/ethereum/execution-specs/blob/5cdb055e069e246a877c8aa018079eb0b9093f57/README.md&quot;&gt;execution-specs&lt;/a&gt;, submitted as an open PR or merged to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devnets/upgradeName/version&lt;/code&gt; branch of the repository. Client developers &lt;strong&gt;MAY&lt;/strong&gt; decide to allow an EIP to be moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; without an &lt;a href=&quot;https://github.com/ethereum/execution-specs/blob/5cdb055e069e246a877c8aa018079eb0b9093f57/README.md&quot;&gt;execution-specs&lt;/a&gt; implementation, but the tests are strictly mandatory.&lt;/p&gt;

&lt;p&gt;Any updates to an EIP that is already at this stage &lt;strong&gt;MUST&lt;/strong&gt; be accompanied by appropriate updates to its implementation and tests in &lt;a href=&quot;https://github.com/ethereum/execution-specs/blob/5cdb055e069e246a877c8aa018079eb0b9093f57/README.md&quot;&gt;execution-specs&lt;/a&gt; if deemed necessary by client developers.&lt;/p&gt;

&lt;h3 id=&quot;included&quot;&gt;Included&lt;/h3&gt;

&lt;p&gt;After network upgrade activation, all included Core EIPs and activated non-Core EIPs &lt;strong&gt;MUST&lt;/strong&gt; be moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included&lt;/code&gt; in the Meta EIP. All other status lists &lt;strong&gt;MUST&lt;/strong&gt; be removed from the Meta EIP.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included&lt;/code&gt; signals that the EIPs have been activated as part of the network upgrade.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;Formalizing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included&lt;/code&gt; stages provides better legibility to both protocol maintainers and the broader Ethereum community.&lt;/p&gt;

&lt;p&gt;The specification tries to minimize steps that &lt;strong&gt;MUST&lt;/strong&gt; be followed to align with Ethereum’s “rough consensus” governance model.&lt;/p&gt;

&lt;p&gt;Assuming it is adopted, the process outlined in this EIP should be used for at least one full network upgrade cycle before moving to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Last Call&lt;/code&gt; and at least two full network upgrade cycles before moving to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Final&lt;/code&gt;. This way, the EIP can be updated to reflect changes made to the process over time.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP does not directly change the Ethereum protocol. It formalizes parts of the current network upgrade planning process.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;None.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Wed, 12 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7723</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7723</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Enshrined Proposer-Builder Separation</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7732 - Enshrined Proposer-Builder Separation&lt;/strong&gt; is in Last Call status. It is authored by Francesco D&apos;Amato &lt;francesco.damato@ethereum.org&gt;, Nico Flaig &lt;nflaig@protonmail.com&gt;, Barnabé Monnot &lt;barnabe.monnot@ethereum.org&gt;, Michael Neuder &lt;michael.neuder@ethereum.org&gt;, Potuz (@potuz), Justin Traglia &lt;jtraglia@ethereum.org&gt;, Terence Tsao &lt;ttsao@offchainlabs.com&gt; and was originally created 2024-06-28. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7732-enshrined-proposer-builder-separation-epbs/19634&quot;&gt;https://ethereum-magicians.org/t/eip-7732-enshrined-proposer-builder-separation-epbs/19634&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP fundamentally changes the way an Ethereum block is validated by decoupling the execution validation from the consensus validation both logically as well as temporally. It does so by introducing a new in-protocol entity called &lt;em&gt;builders&lt;/em&gt; and adding a new duty (submitting &lt;em&gt;payload timeliness attestations&lt;/em&gt;) to Ethereum validators. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayload&lt;/code&gt; field of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconBlockBody&lt;/code&gt; is removed and instead it is replaced by a signed commitment (a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedExecutionPayloadBid&lt;/code&gt; object) from a builder to later reveal the corresponding execution payload. This commitment specifies in particular the blockhash of the execution block and a &lt;em&gt;value&lt;/em&gt; to be paid to the beacon block proposer. When processing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconBlock&lt;/code&gt;, the committed value is deducted from the builder’s beacon chain balance and later a withdrawal is placed to an address, of the proposer’s choosing, in the execution layer. A subset of validators in the beacon committee is assigned to the &lt;em&gt;Payload Timeliness Committee&lt;/em&gt; (PTC), these validators are tasked to attest (by broadcasting a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PayloadAttestationMessage&lt;/code&gt;) to whether the corresponding builder has revealed the committed execution payload (with the right blockhash) in a timely fashion and whether the correspoding blob data was available according to their view. PTC members are not required to validate the execution payload, execution validation is thus deferred until the next beacon block validation. While builder’s are staked entities, their stake is not actively validating the beacon chain, they are not subject to the usual deposit and exit churn/queues and can be staked for as little as 1ETH. While the in-protocol payment via withdrawals is trustlessly deducted from this stake, the protocol also accomodates for trusted payments in the form of &lt;em&gt;promises&lt;/em&gt; to be fulfiled elsewhere.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;This EIP solves a different set of unrelated important problems.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;An overwhelming majority of beacon block proposers outsource the construction of the execution payload within their blocks to a third party (henceforth called a &lt;em&gt;builder&lt;/em&gt;). In order to do so, they request the hash tree root (HTR) of a promised execution payload and submit a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedBlindedBeaconBlock&lt;/code&gt; to a trusted party that is tasked with replacing the HTR with the full execution payload (received from the builder) before broadcasting. This EIP allows for a trust-free fair exchange between the beacon block proposer and the builder, guaranteeing that an honest beacon block proposer will receive payment from the builder regardless of the latter’s actions and that the honest builder’s payload will be the canonical head of the chain regardless of the proposer’s action.&lt;/li&gt;
  &lt;li&gt;Currently, validators have the time between receiving the full beacon block (including an execution payload) and the attesting deadline (4 seconds in Ethereum mainnet) to perform both consensus and execution state transition functions, check blob data availability and evaluate the new head of the blockchain. The remainder of the slot time is spent doing less CPU-intense and critical task. By separating the validation of the execution and consensus part of the block, validators are only tasked to perform the consensus state transition function in this critical time before attesting, while execution and data availability validation is deferred for most of the remainder of the slot (between the builder’s reveal time and the next attestation deadline).&lt;/li&gt;
  &lt;li&gt;By removing the full execution payload size from the consensus block, it allows for faster network propagation on the critical path.&lt;/li&gt;
  &lt;li&gt;It removes the increased reorg likeliness of including blob transactions in blocks given the natural increase in timelines for data availability checks and the fact that the builder may broadcast the blob sidecars even before attestations for the beacon block have been released.&lt;/li&gt;
  &lt;li&gt;It prevents validators from missing attestations and strengthens the weight properties of fork choice in the event that builders produce invalid payloads.&lt;/li&gt;
  &lt;li&gt;It removes the need to use trusted middleware in order to delegate block construction to a builder.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;execution-layer&quot;&gt;Execution Layer&lt;/h3&gt;

&lt;p&gt;No changes are required.&lt;/p&gt;

&lt;h3 id=&quot;consensus-layer&quot;&gt;Consensus Layer&lt;/h3&gt;

&lt;p&gt;The full consensus changes can be found in the consensus-specs Github repository. They are split between:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/beacon-chain.md&quot;&gt;Beacon Chain&lt;/a&gt; changes.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/fork-choice.md&quot;&gt;Fork choice&lt;/a&gt; changes.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/p2p-interface.md&quot;&gt;P2P&lt;/a&gt; changes.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/validator.md&quot;&gt;Honest validator guide&lt;/a&gt; changes.&lt;/li&gt;
  &lt;li&gt;A new &lt;a href=&quot;https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/builder.md&quot;&gt;honest builder&lt;/a&gt; guide.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/fork.md&quot;&gt;Fork logic&lt;/a&gt; changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A summary of the main changes is included below, the &lt;a href=&quot;#rationale&quot;&gt;Rationale&lt;/a&gt; section contains an explanation for most of the design decisions around these changes.&lt;/p&gt;

&lt;h4 id=&quot;beacon-chain-changes&quot;&gt;Beacon chain changes&lt;/h4&gt;

&lt;h5 id=&quot;types&quot;&gt;Types&lt;/h5&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;SSZ equivalent&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderIndex&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Builder registry index&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;constants&quot;&gt;Constants&lt;/h5&gt;

&lt;h6 id=&quot;index-flags&quot;&gt;Index flags&lt;/h6&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_INDEX_FLAG&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(2**40)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Bitwise flag which indicates that a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValidatorIndex&lt;/code&gt; should be treated as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderIndex&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;domains&quot;&gt;Domains&lt;/h5&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMAIN_BEACON_BUILDER&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DomainType(&apos;0x0B000000&apos;)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMAIN_PTC_ATTESTER&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DomainType(&apos;0x0C000000&apos;)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMAIN_PROPOSER_PREFERENCES&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DomainType(&apos;0x0D000000&apos;)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;misc&quot;&gt;Misc&lt;/h5&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_INDEX_SELF_BUILD&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderIndex(UINT64_MAX)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Value which indicates the proposer built the payload&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_PAYMENT_THRESHOLD_NUMERATOR&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(6)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_PAYMENT_THRESHOLD_DENOMINATOR&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(10)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;withdrawal-prefixes&quot;&gt;Withdrawal prefixes&lt;/h5&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_WITHDRAWAL_PREFIX&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bytes1(&apos;0x03&apos;)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Withdrawal credential prefix for a builder&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;preset&quot;&gt;Preset&lt;/h5&gt;

&lt;h6 id=&quot;misc-1&quot;&gt;Misc&lt;/h6&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PTC_SIZE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(2**9)&lt;/code&gt; (= 512)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h6 id=&quot;max-operations-per-block&quot;&gt;Max operations per block&lt;/h6&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_PAYLOAD_ATTESTATIONS&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h6 id=&quot;state-list-lengths&quot;&gt;State list lengths&lt;/h6&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
      &lt;th&gt;Unit&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_REGISTRY_LIMIT&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(2**40)&lt;/code&gt; (= 1,099,511,627,776)&lt;/td&gt;
      &lt;td&gt;Builders&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_PENDING_WITHDRAWALS_LIMIT&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(2**20)&lt;/code&gt; (= 1,048,576)&lt;/td&gt;
      &lt;td&gt;Builder pending withdrawals&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h6 id=&quot;withdrawals-processing&quot;&gt;Withdrawals processing&lt;/h6&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_BUILDERS_PER_WITHDRAWALS_SWEEP&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2**14&lt;/code&gt; (= 16,384)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;configuration&quot;&gt;Configuration&lt;/h5&gt;

&lt;h6 id=&quot;time-parameters&quot;&gt;Time parameters&lt;/h6&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Unit&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MIN_BUILDER_WITHDRAWABILITY_DELAY&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(2**6)&lt;/code&gt; (= 64)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;epochs&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;containers&quot;&gt;Containers&lt;/h5&gt;

&lt;h6 id=&quot;new-containers&quot;&gt;New containers&lt;/h6&gt;

&lt;h6 id=&quot;builder&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Builder&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pubkey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLSPubkey&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint8&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;execution_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExecutionAddress&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;balance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;deposit_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Epoch&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;withdrawable_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Epoch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;builderpendingpayment&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderPendingPayment&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BuilderPendingPayment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;withdrawal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BuilderPendingWithdrawal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;builderpendingwithdrawal&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderPendingWithdrawal&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BuilderPendingWithdrawal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fee_recipient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExecutionAddress&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;builder_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BuilderIndex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;payloadattestationdata&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PayloadAttestationData&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PayloadAttestationData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;beacon_block_root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Root&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Slot&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;payload_present&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boolean&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;blob_data_available&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boolean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;payloadattestation&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PayloadAttestation&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PayloadAttestation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;aggregation_bits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bitvector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PTC_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PayloadAttestationData&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLSSignature&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;payloadattestationmessage&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PayloadAttestationMessage&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PayloadAttestationMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;validator_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ValidatorIndex&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PayloadAttestationData&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLSSignature&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;indexedpayloadattestation&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IndexedPayloadAttestation&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IndexedPayloadAttestation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;attesting_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ValidatorIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PTC_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PayloadAttestationData&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLSSignature&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;executionpayloadbid&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadBid&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ExecutionPayloadBid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parent_block_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Hash32&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parent_block_root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Root&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;block_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Hash32&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;prev_randao&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bytes32&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fee_recipient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExecutionAddress&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gas_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint64&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;builder_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BuilderIndex&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Slot&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;execution_payment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;blob_kzg_commitments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KZGCommitment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_BLOB_COMMITMENTS_PER_BLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;signedexecutionpayloadbid&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedExecutionPayloadBid&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SignedExecutionPayloadBid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExecutionPayloadBid&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLSSignature&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;executionpayloadenvelope&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadEnvelope&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ExecutionPayloadEnvelope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExecutionPayload&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;execution_requests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExecutionRequests&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;builder_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BuilderIndex&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;beacon_block_root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Root&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Slot&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;state_root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Root&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;signedexecutionpayloadenvelope&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedExecutionPayloadEnvelope&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SignedExecutionPayloadEnvelope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExecutionPayloadEnvelope&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLSSignature&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;modified-containers&quot;&gt;Modified containers&lt;/h6&gt;

&lt;h6 id=&quot;beaconblockbody&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconBlockBody&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: The removed fields (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_payload&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blob_kzg_commitments&lt;/code&gt;, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_requests&lt;/code&gt;) now exist in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadEnvelope&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BeaconBlockBody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;randao_reveal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLSSignature&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;eth1_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Eth1Data&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;graffiti&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bytes32&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;proposer_slashings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ProposerSlashing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_PROPOSER_SLASHINGS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;attester_slashings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttesterSlashing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_ATTESTER_SLASHINGS_ELECTRA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;attestations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Attestation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_ATTESTATIONS_ELECTRA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;deposits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_DEPOSITS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;voluntary_exits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SignedVoluntaryExit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_VOLUNTARY_EXITS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sync_aggregate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SyncAggregate&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [Modified in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Removed `execution_payload`
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;bls_to_execution_changes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SignedBLSToExecutionChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_BLS_TO_EXECUTION_CHANGES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [Modified in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Removed `blob_kzg_commitments`
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# [Modified in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Removed `execution_requests`
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;signed_execution_payload_bid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SignedExecutionPayloadBid&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;payload_attestations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PayloadAttestation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_PAYLOAD_ATTESTATIONS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;beaconstate&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconState&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BeaconState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;genesis_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint64&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;genesis_validators_root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Root&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Slot&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Fork&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;latest_block_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BeaconBlockHeader&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;block_roots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SLOTS_PER_HISTORICAL_ROOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;state_roots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SLOTS_PER_HISTORICAL_ROOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;historical_roots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HISTORICAL_ROOTS_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;eth1_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Eth1Data&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;eth1_data_votes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Eth1Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EPOCHS_PER_ETH1_VOTING_PERIOD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SLOTS_PER_EPOCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;eth1_deposit_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint64&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;validators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Validator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALIDATOR_REGISTRY_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;balances&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALIDATOR_REGISTRY_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;randao_mixes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EPOCHS_PER_HISTORICAL_VECTOR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;slashings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EPOCHS_PER_SLASHINGS_VECTOR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;previous_epoch_participation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParticipationFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALIDATOR_REGISTRY_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;current_epoch_participation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParticipationFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALIDATOR_REGISTRY_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;justification_bits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bitvector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JUSTIFICATION_BITS_LENGTH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;previous_justified_checkpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Checkpoint&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;current_justified_checkpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Checkpoint&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;finalized_checkpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Checkpoint&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inactivity_scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALIDATOR_REGISTRY_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;current_sync_committee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SyncCommittee&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;next_sync_committee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SyncCommittee&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [Modified in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Removed `latest_execution_payload_header`
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;latest_execution_payload_bid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExecutionPayloadBid&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;next_withdrawal_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WithdrawalIndex&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;next_withdrawal_validator_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ValidatorIndex&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;historical_summaries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HistoricalSummary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HISTORICAL_ROOTS_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;deposit_requests_start_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint64&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;deposit_balance_to_consume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;exit_balance_to_consume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;earliest_exit_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Epoch&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;consolidation_balance_to_consume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;earliest_consolidation_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Epoch&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pending_deposits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PendingDeposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PENDING_DEPOSITS_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pending_partial_withdrawals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PendingPartialWithdrawal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PENDING_PARTIAL_WITHDRAWALS_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pending_consolidations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PendingConsolidation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PENDING_CONSOLIDATIONS_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;proposer_lookahead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ValidatorIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MIN_SEED_LOOKAHEAD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SLOTS_PER_EPOCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;builders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUILDER_REGISTRY_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;next_withdrawal_builder_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BuilderIndex&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;execution_payload_availability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bitvector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SLOTS_PER_HISTORICAL_ROOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;builder_pending_payments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BuilderPendingPayment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SLOTS_PER_EPOCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;builder_pending_withdrawals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BuilderPendingWithdrawal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUILDER_PENDING_WITHDRAWALS_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;latest_block_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Hash32&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [New in Gloas:EIP7732]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;payload_expected_withdrawals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Withdrawal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_WITHDRAWALS_PER_PAYLOAD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconState&lt;/code&gt; container is modified with the addition of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;builders&lt;/code&gt;, of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[Builder, BUILDER_REGISTRY_LIMIT]&lt;/code&gt; to track the new in-protocol staked builders.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next_withdrawal_builder_index&lt;/code&gt; of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderIndex&lt;/code&gt; to help tracking builder withdrawals.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_payload_availability&lt;/code&gt;, of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bitvector[SLOTS_PER_HISTORICAL_ROOT]&lt;/code&gt; to track the presence of execution payloads on the canonical chain.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;builder_pending_payments&lt;/code&gt;, of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH]&lt;/code&gt; to track pending payments from builders to proposers before the execution payload has been processed.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;builder_pending_withdrawals&lt;/code&gt;, of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT]&lt;/code&gt; to track pending withdrawals to the execution layer with the builders’ payments.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latest_block_hash&lt;/code&gt;, of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hash32&lt;/code&gt;, to track the blockhash of the last execution payload in the blockchain.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload_expected_withdrawals&lt;/code&gt; of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]&lt;/code&gt; to track the latest withdrawals that were deducted in the consensus layer and need to still be honored in the Execution Layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconBlockBody&lt;/code&gt; is modified with the addition of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signed_execution_payload_bid&lt;/code&gt; of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedExecutionPayloadBid&lt;/code&gt; with the builder’s commitment.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload_attestations&lt;/code&gt; of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[PayloadAttestation, MAX_PAYLOAD_ATTESTATIONS]&lt;/code&gt; a list of PTC attestations from the previous slot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadHeader&lt;/code&gt; object is changed (and renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadBid&lt;/code&gt;) to only track the minimum information needed to commit to a builder’s payload.&lt;/p&gt;

&lt;p&gt;State transition logic is modified by:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A new beacon state getter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_ptc&lt;/code&gt; returns the PTC members for a given slot.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_withdrawals&lt;/code&gt; is modified as follows. Withdrawals are obtained directly from the beacon state instead of the execution payload. They are deducted from the beacon chain. The beacon state &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latest_withdrawals_root&lt;/code&gt; is updated with the HTR of this list. The next execution payload MUST include withdrawals matching the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state.latest_withdrawals_root&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_execution_payload&lt;/code&gt; is removed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_block&lt;/code&gt;. Instead a new function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_execution_payload_bid&lt;/code&gt; is included, this function validates the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedExecutionPayloadBid&lt;/code&gt; included in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconBlockBody&lt;/code&gt;, ensures the payment from the builder’s balance can be deducted and adds a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderPendingPayment&lt;/code&gt; object to the beacon state.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_deposit_request&lt;/code&gt; is removed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_operations&lt;/code&gt; and deferred until &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_execution_payload&lt;/code&gt;. Special care is added for deposit requests from new validator pubkeys, with withdrawal credentials starting with the prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_WITHDRAWAL_PREFIX&lt;/code&gt;. These deposits are immediately added to the beacon chain and processed as new builders.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_withdrawal_request&lt;/code&gt; is removed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_operations&lt;/code&gt; and deferred until &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_execution_payload&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_consolidation_request&lt;/code&gt; is removed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_operations&lt;/code&gt; and deferred until &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_execution_payload&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;A new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_payload_attestation&lt;/code&gt; is added to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_operations&lt;/code&gt;, this function validates the payload timeliness attestations broadcast by the PTC members.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_execution_payload&lt;/code&gt; is now called as a separate helper when receiving a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedExecutionPayloadEnvelope&lt;/code&gt; on the P2P layer. This function in particular checks that the HTR of the resulting beacon state coincides with the committed one in the payload envelope. On sucessful processing of the execution payload, the corresponding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderPendingPayment&lt;/code&gt; is removed from the beacon state and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderPendingWithdrawal&lt;/code&gt; is queued.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Epoch processing is modified by addition of a new helper function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_builder_pending_payments&lt;/code&gt;, that processes the builder pending payments from those payloads that were not included in the canonical chain. 
Although there is no change in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttestationData&lt;/code&gt; object, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt; field which is unused since the Electra fork, is now repurposed to signal payload availability. The value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; is used when attesting to the current beacon block or a past beacon block without a payload present, and the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; is used to attest to a past beacon block with a payload present.&lt;/p&gt;

&lt;h4 id=&quot;fork-choice-changes&quot;&gt;Fork-Choice changes&lt;/h4&gt;

&lt;p&gt;Forkchoice is changed substantially to deal with the fact that forkchoice nodes can have different payload content.&lt;/p&gt;

&lt;h4 id=&quot;p2p-changes&quot;&gt;P2P changes&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;A new global topic for broadcasting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedExecutionPayloadBid&lt;/code&gt; messages (builder bids).&lt;/li&gt;
  &lt;li&gt;A new global topic for broadcasting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PayloadAttestationMessage&lt;/code&gt; objects.&lt;/li&gt;
  &lt;li&gt;A new global topic for broadcasting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProposerPreferences&lt;/code&gt; objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;engine-api&quot;&gt;Engine API&lt;/h3&gt;

&lt;p&gt;No changes needed.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;staked-builders&quot;&gt;Staked builders&lt;/h3&gt;

&lt;p&gt;Being a builder is a new type of entity tracked in the beacon state. As such builders are staked in the beacon chain and they have their own withdrawal credential prefix. This allows for in-protocol trustless enforcement of the builder’s payment to the proposer. Alternatively, payment could be enforced in the Execution Layer (EL) at the cost of adding the corresponding EL consensus-changing logic. Payments in the EL have the advantage of not requiring the builder to periodically submit deposit transactions to replenish their validator balance. Both systems require availability of funds before the payload is revealed: in the Consensus Layer (CL) this is done by getting builders to stake. In the EL this is done with a balance check and a payment transaction. This transaction can be checked without executing the payload only if it the first transaction of the block.&lt;/p&gt;

&lt;h3 id=&quot;delayed-validation&quot;&gt;Delayed validation&lt;/h3&gt;

&lt;p&gt;The Payload Timeliness Committee members do not need to validate the execution payload before attesting to it. They perform basic checks such as verifying the builder’s signature, and the correct blockhash is included. This takes away the full execution payload validation from the hot path of validation of an Ethereum block, giving the next proposer 6 seconds (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SECONDS_PER_SLOT * 2 // INTERVALS_PER_SLOT&lt;/code&gt;) to validate the payload and every other validator 9 seconds (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SECONDS_PER_SLOT * 3 // INTERVALS_PER_SLOT&lt;/code&gt;). From a user UX perspective, a transaction included in slot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; by the builder is not widely validated until the proposer of slot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N+1&lt;/code&gt; releases their beacon block on top of block &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; first and the attesters of slot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N+1&lt;/code&gt; vote on this beacon block as the head of the chain.&lt;/p&gt;

&lt;h3 id=&quot;fork-choice&quot;&gt;Fork choice&lt;/h3&gt;

&lt;p&gt;The following features of fork choice are guaranteed under specified margins of security:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Proposer unconditional payment.&lt;/li&gt;
  &lt;li&gt;Builder reveal safety.&lt;/li&gt;
  &lt;li&gt;Builder withhold safety.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Proposer unconditional payment refers to the following. An Ethereum slot can be either:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Full&lt;/em&gt;: both the beacon block and the execution payload have been revealed and included on-chain.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Skipped&lt;/em&gt;: No beacon block (and therefore no execution payload) has been included on-chain for this slot.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Empty&lt;/em&gt;: The beacon block has been included on-chain, but the committed execution payload has not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Proposer unconditional payment refers to the fact that in the third scenario the beacon block proposer received payment from the corresponding builder.&lt;/p&gt;

&lt;p&gt;Builder reveal safety refers to the fact that if the builder acted honestly and revealed a payload in a timely fashion (as attested by the PTC) then the revealed payload will be included on-chain.&lt;/p&gt;

&lt;p&gt;Builder withhold safety refers to the fact that if some beacon block containing a builder’s commitment is withheld and revealed late, the builder will not be charged the value of the bid. In particular, the payload does not even need to be revealed in this case.&lt;/p&gt;

&lt;p&gt;The precise method by which these safety mechanisms are enforced is by allowing attestations to also signal their view of the slot as in either of the above options &lt;em&gt;Full&lt;/em&gt;, &lt;em&gt;Skipped&lt;/em&gt; or &lt;em&gt;Empty&lt;/em&gt;. For this, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt; field in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttestationData&lt;/code&gt; is used as explained above.&lt;/p&gt;

&lt;h3 id=&quot;ptc-equivocations&quot;&gt;PTC equivocations&lt;/h3&gt;

&lt;p&gt;There is no penalty for PTC nor payload equivocation (that is revealing the right payload and also a withheld message at the same time). A collusion of a builder controlling network partition with a single malicious PTC member could cause a split view by achieving consensus both on payload withheld and a payload present. This could be mitigated by setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PAYLOAD_TIMELY_THRESHOLD&lt;/code&gt; to be 2/3 of the PTC, in which case the malicious operator would have to control at least 33% of the PTC.&lt;/p&gt;

&lt;p&gt;Another mitigation mechanism is to add new slashing conditions for payload equivocation or PTC equivocations (both are signed messages by validators).&lt;/p&gt;

&lt;p&gt;Since this attack results in a split view at a cost for the builder (the payload is revealed and may not be included) this EIP opted for simplicity of implementation.&lt;/p&gt;

&lt;h3 id=&quot;withdrawals&quot;&gt;Withdrawals&lt;/h3&gt;

&lt;p&gt;Withdrawals from the beacon chain are complex in nature, they involve removing funds from one layer and crediting them on another, with different trigger mechanisms that can start from either layer. Before applying the consensus layer state transition function to a given beacon state &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pre_state&lt;/code&gt; and processing a given signed beacon block &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block&lt;/code&gt;, the set of withdrawals that are expected to be deducted from the beacon chain are completely determined by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pre_state&lt;/code&gt;. Previous to this EIP the set of withdrawals that are credited on the execution layer are included in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block&lt;/code&gt;. The block is deemed invalid if these withdrawals do not match. With the separation included in this EIP, these operations of deducting and crediting become asynchronous:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;When processing the beacon block, the withdrawals are deducted from the beacon chain.&lt;/li&gt;
  &lt;li&gt;The set of withdrawals just deducted is committed to the beacon state &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post_state&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;When processing any execution payload whose parent beacon state is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post_state&lt;/code&gt;, the payload is deemed invalid if it doesn’t include precisely the list of withdrawals committed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post_state&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This asynchronous mechanism has some consequences as slots may be &lt;em&gt;empty&lt;/em&gt; as defined above. In these cases, the consensus layer does not process any more withdrawals until an execution payload has fulfilled the outstanding ones. An alternative design would be to defer all of withdrawal processing to the execution payload validation phase (ie. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_execution_payload&lt;/code&gt;). This has the advantage of not needing to track the fulfilled withdrawals on the beacon chain. The logic changes when several payloads are missing, in which case balances on the beacon chain change and therefore a withdrawal that would be possible with the former mechanism may be different, or even impossible with the latter.&lt;/p&gt;

&lt;h3 id=&quot;three-state-transition-functions&quot;&gt;Three state transition functions&lt;/h3&gt;

&lt;p&gt;The current EIP adds an extra state transition function to the block processing in Ethereum. Processing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedBeaconBlock&lt;/code&gt; changes the consensus layer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeaconState&lt;/code&gt;. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedExecutionPayloadEnvelope&lt;/code&gt; changes both the execution layer state and the consensus layer one. As such, the envelope commits to the consensus layer post-state-transition beacon state root.&lt;/p&gt;

&lt;h3 id=&quot;compatible-designs&quot;&gt;Compatible designs&lt;/h3&gt;

&lt;h4 id=&quot;inclusion-lists&quot;&gt;Inclusion lists&lt;/h4&gt;

&lt;p&gt;This EIP is fully compatible with forkchoice enforced inclusion lists or similar.&lt;/p&gt;

&lt;h4 id=&quot;slot-auctions&quot;&gt;Slot auctions&lt;/h4&gt;

&lt;p&gt;A simple change to this EIP is to remove the blockhash commitment from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignedExecutionPayloadBid&lt;/code&gt;. This allows the builder to commit any payload to the slot. A preliminary security analysis shows that payload equivocation does not weaken fork choice’s FFG. Some advantages of Slot auctions include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Better user experience as any submitted transaction can be included in the next block (with block auctions a transaction sent in the first half of the slot can only be included in the following block).&lt;/li&gt;
  &lt;li&gt;Longer continuous time to build blocks.&lt;/li&gt;
  &lt;li&gt;Better compatibility designs with fork choice enforced inclusion list proposals.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP introduces backward incompatible changes to the block validation rule set on the consensus layer and must be accompanied by a hard fork.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;free-option-problem&quot;&gt;Free option problem&lt;/h3&gt;

&lt;p&gt;Economically rational but malicious (as defined by the honest builder guide) builders may chose to withhold their payload in the event that it would be profitable for them. This could result in missed slots and degradation of user experience of Ethereum. Some preliminary data in the form of simulation suggests that the number of these occurrences may be noticeable. Some mitigations were proposed in the form of variable penalties for builders that fail to include their payload envelopes in the canonical chain.&lt;/p&gt;

&lt;h3 id=&quot;builder-safety&quot;&gt;Builder safety&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;A colluding set of proposers and attesters controlling consecutive blocks and more than 20% of the total stake can reorg a builder’s payload and force it to pay the bid’s value.&lt;/li&gt;
  &lt;li&gt;There is no possible &lt;em&gt;unbundling&lt;/em&gt; of the builder’s payload in the same slot, that is, if the builder reveals a payload for the head of the chain, no other payload is possible for the current slot.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;malicious-ptc&quot;&gt;Malicious PTC&lt;/h3&gt;

&lt;p&gt;The expected time for a malicious attacker, controlling 35% of the total stake, to have a majority control on the PTC is 205 000 years.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 28 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7732</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7732</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Code Index</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7744 - Code Index&lt;/strong&gt; is in Last Call status. It is authored by Tim Pechersky (@peersky) &lt;t@peersky.xyz&gt; and was originally created 2024-07-16. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-7744-code-index/20569&quot;&gt;https://ethereum-magicians.org/t/erc-7744-code-index/20569&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP defines a standard interface for indexing smart contracts on Ethereum by their bytecode hash. This enables trustless discovery and verification of contract code, facilitating use cases like bytecode signing, whitelisting, and decentralized distribution mechanisms.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Existing contract discovery relies on addresses, which are non-deterministic and can be obfuscated through proxies. Indexing by bytecode hash provides a deterministic and tamper-proof way to identify and verify contract code, enhancing security and trust in the Ethereum ecosystem.&lt;/p&gt;

&lt;p&gt;Consider a security auditor who wants to attest to the integrity of a contract’s code. By referencing bytecode hashes, auditors can focus their audit on the bytecode itself, without needing to assess deployment parameters or storage contents. This method verifies the integrity of a contract’s codebase without auditing the entire contract state.&lt;/p&gt;

&lt;p&gt;Additionally, bytecode referencing allows whitelist contracts before deployment, allowing developers to get pre-approval for their codebase without disclosing the code itself, or even pre-setup infrastructure that will change it behavior upon adding some determined functionality on chain.&lt;/p&gt;

&lt;p&gt;For developers relying on extensive code reuse, bytecode referencing protects against malicious changes that can occur with address-based referencing through proxies. This builds long-term trust chains extending to end-user applications.&lt;/p&gt;

&lt;p&gt;For decentralized application (dApp) developers, a code index can save gas costs by allowing them to reference existing codebases instead of redeploying them, optimizing resource usage. This can be useful for dApps that rely on extensive re-use of same codebase as own dependencies.&lt;/p&gt;

&lt;h3 id=&quot;why-this-registry-needs-to-be-an-erc&quot;&gt;Why this registry needs to be an ERC&lt;/h3&gt;

&lt;p&gt;The Code Index is essential for trustless and secure smart contract development. By standardizing the interface for indexing contracts by their bytecode, developers can easily integrate this feature into their smart contracts, enhancing the security and trustworthiness of the Ethereum ecosystem.&lt;/p&gt;

&lt;p&gt;Its simplicity and generic nature make it suitable for a wide range of applications. The ability to globally reference the same codebase makes it an ideal candidate for standardization.&lt;/p&gt;

&lt;p&gt;Ultimately, this feature should be incorporated into EIP standards, as it is a fundamental building block for trustless and secure smart contract development. This standard is a step towards this goal.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// SPDX-License-Identifier: CC0-1.0
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IERC7744&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;./IERC7744.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @title Byte Code Indexer Contract
 * @notice You can use this contract to index contracts by their bytecode.
 * @dev This allows to query contracts by their bytecode instead of addresses.
 * @author Tim Pechersky (@Peersky)
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC7744&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC7744&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isEIP7702&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;account&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;extcodecopy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;account&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Copy first 3 bytes to memory
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Load the 3 bytes from memory
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xef0100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isValidContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;codeHash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;codeHash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEIP7702&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Registers a contract in the index by its bytecode hash
     * @param container The contract to register
     * @dev `msg.codeHash` will be used
     * @dev It will revert if the contract is already indexed or if returns EIP7702 delegated EOA
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;etalon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isValidContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Invalid container&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etalon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isValidContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etalon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;revert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alreadyExists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Indexed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Returns the contract address by its bytecode hash
     * @dev returns zero if the contract is not indexed
     * @param id The bytecode hash
     * @return The contract address
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;deployment-method&quot;&gt;Deployment method&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CodeIndex&lt;/code&gt; contract is deployed at: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC0De1D1126b6D698a0073A4e66520111cEe22F62&lt;/code&gt; using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; via the deterministic deployer at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4e59b44847b379578588920ca78fbf26c0b4956c&lt;/code&gt; with a salt of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x9425035d50edcd7504fe5eeb5df841cc74fe6cccd82dca6ee75bcdf774bd88d9&lt;/code&gt; is obtained by seeking a vanity address starting with meaningful name “Code ID (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c0de1d&lt;/code&gt;) for a bytecode compiled with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solc 0.8.28&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solc --input-file src/ERC7744.sol --bin --optimize --optimize-runs 2000 --metadata-hash none --via-ir --optimize-yul&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bytecode over Addresses&lt;/strong&gt;: Bytecode is deterministic and can be verified on-chain, while addresses are opaque and mutable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reverting on re-indexing&lt;/strong&gt;: There is small, yet non-zero probability of hash collision attack. Disallowing updates to indexed location of bytecode coupes with this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simple Interface&lt;/strong&gt;: The interface is minimal and focused to maximize composability and ease of implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Library Implementation&lt;/strong&gt;: Implementing this as a library would limit its impact, making code reuse more difficult and lacking a single, official source of truth. By establishing this as an ERC, we ensure standardization and widespread adoption, driving the ecosystem forward.&lt;/p&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;Reference implementation of the Code Index can be found in the assets folder. There you can find the &lt;a href=&quot;/assets/eip-7744/IERC7744.sol&quot;&gt;interface&lt;/a&gt; and the &lt;a href=&quot;/assets/eip-7744/ERC7744.sol&quot;&gt;implementation&lt;/a&gt; of the Code Index.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Malicious Code&lt;/strong&gt;: The index does NOT guarantee the safety or functionality of indexed contracts. Users MUST exercise caution and perform their own due diligence before interacting with indexed contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storage contents of registered contracts&lt;/strong&gt;: The index only refers to the bytecode of the contract, not the storage contents. This means that the contract state is not indexed and may change over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt;&lt;/strong&gt;: The index does not index the EIP-7702 delegated accounts. During attempt to register, it checks if contract code begins with reserved delegation designator &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xef0100&lt;/code&gt; and if so, it will revert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-Destruct Contracts&lt;/strong&gt;: In case of indexed contract storage becomes empty, contracts may be re-indexed, During register function call, if contract is already indexed, we run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isValidContainer&lt;/code&gt; check on the indexed address. It it fails, re-indexing is allowed with a newly specified address.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Tue, 16 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7744</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7744</guid>
      </item>
      
    
      
    
      
      
      <item>
        <title>Composable Security Middleware Hooks</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7746 - Composable Security Middleware Hooks&lt;/strong&gt; is in Last Call status. It is authored by Tim Pechersky (@peersky) and was originally created 2024-07-17. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-7746-composable-security-middleware-hooks/19471&quot;&gt;https://ethereum-magicians.org/t/erc-7746-composable-security-middleware-hooks/19471&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP proposes a standard interface, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer&lt;/code&gt;, for implementing composable security layers in smart contracts. These layers act as middleware, enabling runtime validation of function calls before and after execution, independent of the protected contract’s logic. This approach facilitates modular security, allowing independent providers to manage and upgrade security layers across multiple contracts.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Current smart contract security practices often rely on monolithic validation logic within the contract itself. This can lead to tightly coupled code, making it difficult to isolate and address security concerns. Better structured architecture is needed, middleware like approach is widely used in the industry, allowing to wrap calls in other calls in generic and repeatable pattern with same call signatures.&lt;/p&gt;

&lt;p&gt;The Security Layers Standard introduces a modular approach, enabling:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Independent Security Providers:&lt;/strong&gt; Specialized security providers can focus on developing and maintaining specific security checks.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Composable Security:&lt;/strong&gt; Layers can be combined to create comprehensive security profiles tailored to individual contract needs.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Upgradability:&lt;/strong&gt; Security layers can be updated without requiring changes to the protected contract.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; Layers can perform a wide range of validation checks, including access control, input sanitization, output verification, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having a generalized standard for such layers can help to build more secure and modular systems as well as enable security providers to build generic, service-oriented security oracle solutions.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;A contract implementing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer&lt;/code&gt; interface MUST provide two functions:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// SPDX-License-Identifier: CC0-1.0
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ILayer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;/// @notice Validates a function call before execution.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param configuration Layer-specific configuration data.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param selector The function selector being called.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param sender The address initiating the call.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param value The amount of ETH sent with the call (if any).
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param data The calldata for the function call.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return beforeCallResult Arbitrary data to be passed to `afterCallValidation`.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @dev MUST revert if validation fails.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beforeCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Validates a function call after execution.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param configuration Layer-specific configuration data.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param selector The function selector being called.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param sender The address initiating the call.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param value The amount of ETH sent with the call (if any).
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param data The calldata for the function call.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param beforeCallResult The data returned by `beforeCallValidation`.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @dev MUST revert if validation fails.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;afterCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beforeCallResult&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A protected contract MAY integrate security layers by calling the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;beforeCallValidation&lt;/code&gt; function before executing its logic and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;afterCallValidation&lt;/code&gt; function afterwards. Multiple layers can be registered and executed in a defined order. The protected contract MUST revert if any layer reverts.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layerConfig&lt;/code&gt; parameter allows for layer-specific customization, enabling a single layer implementation to serve multiple contracts with varying requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;non-static calls&lt;/strong&gt;: Layers can maintain their own state, allowing for more complex validation logic (e.g., rate limiting, usage tracking).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strict Validation&lt;/strong&gt;: Reverts on validation failure ensure a fail-safe mechanism, preventing execution of potentially harmful transactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gas Costs&lt;/strong&gt;: Layers naturally will have gas costs associated with their execution. However, the benefits of enhanced security and modularity outweigh these costs, especially as blockchain technology continues to evolve and we expect gas costs to decrease over time.&lt;/p&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;A reference implementation of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer&lt;/code&gt; interface and a sample protected contract can be found in the repository:
In the &lt;a href=&quot;/assets/eip-7746/ILayer.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer.sol&lt;/code&gt;&lt;/a&gt; a reference interface is provided.&lt;/p&gt;

&lt;p&gt;In this test, a &lt;a href=&quot;/assets/eip-7746/test/Protected.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protected.sol&lt;/code&gt;&lt;/a&gt; contract is protected by a &lt;a href=&quot;/assets/eip-7746/test/RateLimitLayer.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateLimitLayer.sol&lt;/code&gt;&lt;/a&gt; layer. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateLimitLayer&lt;/code&gt; implements the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer&lt;/code&gt; interface and enforces a rate which client has configured.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Drainer&lt;/code&gt; simulates a vulnerable contract that acts in a malicious way. In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test.ts&lt;/code&gt; The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Drainer&lt;/code&gt; contract is trying to drain the funds from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protected&lt;/code&gt; contract. It is assumed that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protected&lt;/code&gt; contract has bug that allows partial unauthorized access to the state.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateLimitLayer&lt;/code&gt; is configured to allow only 10 transactions per block from same sender. The test checks that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Drainer&lt;/code&gt; contract is not able to drain the funds from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protected&lt;/code&gt; contract.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Layer Trust&lt;/strong&gt;: Thoroughly audit and vet any security layer before integrating it into your contract. Malicious layers can compromise contract security.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Wed, 17 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7746</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7746</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Block Gas Accounting without Refunds</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7778 - Block Gas Accounting without Refunds&lt;/strong&gt; is in Last Call status. It is authored by Ben Adams (@benaadams), Toni Wahrstätter (@nerolation) and was originally created 2024-10-01. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7778-prevent-block-gas-smuggling/21234&quot;&gt;https://ethereum-magicians.org/t/eip-7778-prevent-block-gas-smuggling/21234&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP modifies the block gas accounting mechanism to prevent the circumvention of block gas limits. It proposes that gas refunds, particularly those from SSTORE operations setting storage slots to zero, should not reduce the gas counted toward the block gas limit, while still being applied to transaction gas costs for users.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Currently, gas refunds from operations like clearing storage slots (setting to zero) reduce both the transaction gas cost for users and the gas counted toward the block gas limit. This creates a discrepancy between the computational work performed and the gas accounted for in the block.&lt;/p&gt;

&lt;p&gt;Example: Block &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20878522&lt;/code&gt; shows a net usage of 28.5 MGas, but contains 4.01 MGas of refunds, bringing the gross usage to 32.51 MGas—exceeding the block gas limit by 2.51 MGas.&lt;/p&gt;

&lt;p&gt;This mechanism can be exploited to perform more operations in a block than the gas limit intends to allow, potentially leading to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Network instability due to oversized blocks&lt;/li&gt;
  &lt;li&gt;Denial-of-service vectors&lt;/li&gt;
  &lt;li&gt;Computational loads exceeding the intended block gas limit&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;gas-accounting-changes&quot;&gt;Gas Accounting Changes&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;User Gas Accounting (Unchanged):&lt;/strong&gt;&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;Users continue to receive gas refunds for operations that qualify (e.g., setting storage to zero)&lt;/li&gt;
      &lt;li&gt;Transaction gas: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_spent = max(tx_gas_used - gas_refund, calldata_floor_gas_cost)&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Block Gas Accounting (Modified):&lt;/strong&gt;&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;When calculating gas for block gas limit enforcement, refunds are not subtracted&lt;/li&gt;
      &lt;li&gt;Block gas accounting becomes: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.gas_used += max(tx_gas_used, calldata_floor_gas_cost)&lt;/code&gt; (incorporating the calldata floor from &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt;)&lt;/li&gt;
      &lt;li&gt;Storage discounts that reflect actual reduced computational work (e.g., warm storage access, reverting to original values) remain applied to block gas accounting&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;aligning-gas-limits-with-computational-work&quot;&gt;Aligning Gas Limits with Computational Work&lt;/h3&gt;

&lt;p&gt;The block gas limit is designed to constrain the computational load per block. Gas refunds were introduced to incentivize “cleaning up” the state, not to allow exceeding computational limits. By excluding refunds from block gas accounting, we ensure the block gas limit effectively constrains computational load&lt;/p&gt;

&lt;h3 id=&quot;preserving-user-incentives&quot;&gt;Preserving User Incentives&lt;/h3&gt;

&lt;p&gt;Users still receive gas refunds, maintaining incentives for efficient state management. Only the accounting for block-level constraints changes, not the economics for individual users&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;This change is not backwards compatible and requires a hard fork&lt;/li&gt;
  &lt;li&gt;User and developer experience for individual transactions remains unchanged&lt;/li&gt;
  &lt;li&gt;Block producers need to adjust their transaction selection algorithms to account for the new gas accounting rules&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;SSTORE Operations:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Setting storage to zero: User receives refund, but block gas accounting uses full cost&lt;/li&gt;
      &lt;li&gt;Verify blocks containing many storage-clearing operations still adhere to gas limits&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Block Gas Limit Edge Cases:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Construct blocks with varying amounts of refundable operations&lt;/li&gt;
      &lt;li&gt;Ensure blocks cannot exceed gas limits through refund mechanisms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Transaction Gas vs Block Gas:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Verify that transaction costs for users remain unchanged&lt;/li&gt;
      &lt;li&gt;Confirm block gas accounting properly excludes refunds&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Eliminates potential denial-of-service vectors that exploit gas refunds to exceed block computational limits&lt;/li&gt;
  &lt;li&gt;Improves predictability of block processing times by enforcing stricter limits on computational work&lt;/li&gt;
  &lt;li&gt;Prevents miners/validators from including transactions that collectively contain more computational work than intended&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Tue, 01 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7778</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7778</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>SLOTNUM opcode</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7843 - SLOTNUM opcode&lt;/strong&gt; is in Last Call status. It is authored by Marc Harvey-Hill (@Marchhill) and was originally created 2024-12-06. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7843-slotnum-opcode/22234&quot;&gt;https://ethereum-magicians.org/t/eip-7843-slotnum-opcode/22234&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP proposes to add a new opcode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOTNUM&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4b&lt;/code&gt;), that returns the corresponding slot number for the current block.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;There are currently two ways to get the current slot number onchain:&lt;/p&gt;

&lt;p&gt;1) Calculate from the block timestamp. This requires hardcoding the chain slot length into a smart contract.&lt;/p&gt;

&lt;p&gt;2) Provide the slot number as calldata and prove it against the beacon block root (using &lt;a href=&quot;/EIPS/eip-4788&quot;&gt;EIP-4788&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Both of these approaches have significant drawbacks. (1) would break contracts in the event of a change to the slot length. (2) is expensive in terms of gas, encouraging approach (1) to be used instead.&lt;/p&gt;

&lt;p&gt;A better approach is for the slot length to be abstracted away from applications, and instead the slot number can be calculated in the consensus layer client and exposed by an opcode. This paves the way for future changes to the slot length.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;A new opcode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOTNUM&lt;/code&gt; is introduced at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4b&lt;/code&gt;. It shall return one stack element.&lt;/p&gt;

&lt;h3 id=&quot;output&quot;&gt;Output&lt;/h3&gt;

&lt;p&gt;One element &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slotNumber&lt;/code&gt; is added to the stack; it is equal to the corresponding slot number for this block. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slotNumber&lt;/code&gt; is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt; in big endian encoding.&lt;/p&gt;

&lt;h3 id=&quot;gas-cost&quot;&gt;Gas Cost&lt;/h3&gt;

&lt;p&gt;The gas cost for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOTNUM&lt;/code&gt; is a fixed fee of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;rpc-changes&quot;&gt;RPC changes&lt;/h3&gt;

&lt;p&gt;The slot number is calculated in the consensus layer and passed to the execution layer through the engine API.&lt;/p&gt;

&lt;h4 id=&quot;header-extension&quot;&gt;Header extension&lt;/h4&gt;

&lt;p&gt;The header encoding shall be extended to include a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slotNumber&lt;/code&gt; field of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;engine-api-changes&quot;&gt;Engine API changes&lt;/h4&gt;

&lt;p&gt;New objects &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadV4&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PayloadAttributesV4&lt;/code&gt; are introduced, adding a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slotNumber&lt;/code&gt; field of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;. The methods &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_newPayloadV5&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_getPayloadV6&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_forkchoiceUpdatedV4&lt;/code&gt; are added, to use the new objects.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;gas-price&quot;&gt;Gas Price&lt;/h3&gt;

&lt;p&gt;The opcode is priced to match similar opcodes in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;W_base&lt;/code&gt; set.&lt;/p&gt;

&lt;h3 id=&quot;calculation-in-consensus-layer&quot;&gt;Calculation in consensus layer&lt;/h3&gt;

&lt;p&gt;The slot number could alternatively be calculated in the execution layer using the timestamp, but it is more appropriate to calculate values pertaining to the beacon chain in the consensus layer. Additionally this avoids code duplication, as the slot number is already calculated in the consensus layer.&lt;/p&gt;

&lt;h3 id=&quot;zk-vm-proving&quot;&gt;ZK-VM proving&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOTNUM&lt;/code&gt; opcode should not increase the complexity of proving EVM execution, as it is similar to existing opcodes such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TIMESTAMP&lt;/code&gt;. The slot number is included in the block header rather than as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_newPayload&lt;/code&gt; parameter, ensuring that the block is self-contained for proving; no extra inputs to the circuit are required.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;No backward compatibility issues found.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;N/A&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;None.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 06 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7843</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7843</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Compute Gas Cost Analysis</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7904 - Compute Gas Cost Analysis&lt;/strong&gt; is in Last Call status. It is authored by Jacek Glen (@JacekGlen), Lukasz Glen (@lukasz-glen), Maria Silva (@misilva73) and was originally created 2025-02-05. It is in the  category of type Informational. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/gas-cost-repricing-to-reflect-computational-complexity/23067&quot;&gt;https://ethereum-magicians.org/t/gas-cost-repricing-to-reflect-computational-complexity/23067&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This document reports an empirical analysis of the runtime of EVM compute operations and precompiles across the major execution clients. Measurements were taken on clients that include the parallel-execution optimizations enabled by &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; (Block-Level Access Lists). Using a target throughput of &lt;strong&gt;100 million gas per second (Mgas/s)&lt;/strong&gt;, the analysis finds that every compute operation and precompile examined already performs at or above that target under the current gas schedule. We therefore conclude that no compute operation or precompile requires a gas-cost increase, and this EIP recommends no changes to the gas schedule.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Earlier revisions of this proposal were Standards Track and aimed to &lt;em&gt;raise&lt;/em&gt; the gas cost of a set of compute operations and precompiles that empirical measurement had shown performing below the target throughput. The intent was to remove these operations as bottlenecks so that the block gas limit could be raised safely.&lt;/p&gt;

&lt;p&gt;Since those measurements were taken, the client-side optimizations unlocked by Block-Level Access Lists (&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;) — parallel disk reads, parallel transaction validation, and executionless state updates — have stabilized across all major execution clients. Re-running the benchmark and estimation pipeline against clients with these optimizations in place changes the picture entirely: the operations that previously appeared underpriced now clear the 100 Mgas/s target comfortably at their current gas costs.&lt;/p&gt;

&lt;p&gt;Because the original motivation for repricing no longer holds, this EIP is recorded as Informational. Its purpose is to document the analysis, preserve the methodology and data for future repricing work, and state the conclusion that no compute gas cost needs to change.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;This EIP specifies &lt;strong&gt;no changes&lt;/strong&gt; to the Ethereum gas schedule. No opcode or precompile gas cost is modified.&lt;/p&gt;

&lt;p&gt;The analysis examined the 18 gas parameters listed below — the opcodes and precompiles that earlier revisions had flagged as candidates for repricing. For each parameter, the table reports the current gas cost against the gas cost implied by the worst-performing client at the 100 Mgas/s target. A proposed value at or below the current value means the operation already meets the throughput target at its current price.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Gas param&lt;/th&gt;
      &lt;th&gt;Current gas&lt;/th&gt;
      &lt;th&gt;Measured at 100 Mgas/s&lt;/th&gt;
      &lt;th&gt;Diff&lt;/th&gt;
      &lt;th&gt;Diff %&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;OPCODE_DIV&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;-3&lt;/td&gt;
      &lt;td&gt;-60%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OPCODE_SDIV&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;-3&lt;/td&gt;
      &lt;td&gt;-60%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OPCODE_MOD&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;-3&lt;/td&gt;
      &lt;td&gt;-60%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OPCODE_SMOD&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;-2&lt;/td&gt;
      &lt;td&gt;-40%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OPCODE_ADDMOD&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;-5&lt;/td&gt;
      &lt;td&gt;-62%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OPCODE_MULMOD&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;-4&lt;/td&gt;
      &lt;td&gt;-50%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OPCODE_KECCAK256_BASE&lt;/td&gt;
      &lt;td&gt;30&lt;/td&gt;
      &lt;td&gt;12&lt;/td&gt;
      &lt;td&gt;-18&lt;/td&gt;
      &lt;td&gt;-60%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OPCODE_KECCAK256_PER_WORD&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;-3&lt;/td&gt;
      &lt;td&gt;-50%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_ECRECOVER&lt;/td&gt;
      &lt;td&gt;3000&lt;/td&gt;
      &lt;td&gt;841&lt;/td&gt;
      &lt;td&gt;-2159&lt;/td&gt;
      &lt;td&gt;-72%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_BLAKE2F_BASE&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;94&lt;/td&gt;
      &lt;td&gt;+94&lt;/td&gt;
      &lt;td&gt;n/a&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_BLAKE2F_PER_ROUND&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_BLS_G1ADD&lt;/td&gt;
      &lt;td&gt;375&lt;/td&gt;
      &lt;td&gt;236&lt;/td&gt;
      &lt;td&gt;-139&lt;/td&gt;
      &lt;td&gt;-37%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_BLS_G2ADD&lt;/td&gt;
      &lt;td&gt;600&lt;/td&gt;
      &lt;td&gt;277&lt;/td&gt;
      &lt;td&gt;-323&lt;/td&gt;
      &lt;td&gt;-54%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_ECADD&lt;/td&gt;
      &lt;td&gt;150&lt;/td&gt;
      &lt;td&gt;108&lt;/td&gt;
      &lt;td&gt;-42&lt;/td&gt;
      &lt;td&gt;-28%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_ECPAIRING_BASE&lt;/td&gt;
      &lt;td&gt;45000&lt;/td&gt;
      &lt;td&gt;8247&lt;/td&gt;
      &lt;td&gt;-36753&lt;/td&gt;
      &lt;td&gt;-82%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_ECPAIRING_PER_POINT&lt;/td&gt;
      &lt;td&gt;34000&lt;/td&gt;
      &lt;td&gt;11712&lt;/td&gt;
      &lt;td&gt;-22288&lt;/td&gt;
      &lt;td&gt;-66%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_POINT_EVALUATION&lt;/td&gt;
      &lt;td&gt;50000&lt;/td&gt;
      &lt;td&gt;23825&lt;/td&gt;
      &lt;td&gt;-26175&lt;/td&gt;
      &lt;td&gt;-52%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PRECOMPILE_P256VERIFY&lt;/td&gt;
      &lt;td&gt;6900&lt;/td&gt;
      &lt;td&gt;3814&lt;/td&gt;
      &lt;td&gt;-3086&lt;/td&gt;
      &lt;td&gt;-45%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Sixteen of the eighteen parameters measure cheaper than the current schedule, and one (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PRECOMPILE_BLAKE2F_PER_ROUND&lt;/code&gt;) is unchanged. The only parameter that measures higher than the current schedule is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLAKE2F&lt;/code&gt; base cost, which is currently unpriced (0 gas); the measured value of 94 gas is negligible relative to typical block gas usage and does not constitute a throughput bottleneck. On this basis, no operation is underpriced to a degree that warrants a gas-cost increase.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;/assets/eip-7904/analysis/2026-06-10/new_gas_proposal&quot;&gt;full proposal report&lt;/a&gt;, including per-client breakdowns and worst-case provenance, accompanies this EIP.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;empirical-estimation-of-gas-costs&quot;&gt;Empirical Estimation of Gas Costs&lt;/h3&gt;

&lt;h4 id=&quot;target-throughput&quot;&gt;Target Throughput&lt;/h4&gt;

&lt;p&gt;A performance target of &lt;strong&gt;100 million gas per second&lt;/strong&gt; is used as the anchor for the analysis. This target reflects the throughput that the optimized clients are expected to sustain, a substantial increase over the historical baseline. An operation is considered adequately priced if its measured runtime at the current gas cost meets or exceeds this rate.&lt;/p&gt;

&lt;h4 id=&quot;data-collection&quot;&gt;Data Collection&lt;/h4&gt;

&lt;p&gt;The estimates are based on the actual time each operation takes to run on the various execution clients. Similar to the methodology used in the Gas Cost Estimator project, we generate synthetic blocks that isolate and stress individual EVM operations.&lt;/p&gt;

&lt;p&gt;Concretely, to benchmark a single operation, different blocks are created by varying the number of times the target operation is executed and by changing the parameter values to the operation. The EEST benchmark suite contains the tests used to generate these blocks.&lt;/p&gt;

&lt;p&gt;Then, the Benchmarkoor tool is used to collect the needed metrics. This tool returns the total execution time of the block and the number of times each operation was executed. Each test block is run multiple times on each client to account for variability in execution time. The clients measured in the latest run are Besu, Erigon, ethrex, Geth, Nethermind, and Reth.&lt;/p&gt;

&lt;h5 id=&quot;what-about-dynamic-costs&quot;&gt;What about dynamic costs?&lt;/h5&gt;

&lt;p&gt;Some operations have a dynamic component to their costs. For example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KECCAK256&lt;/code&gt; opcode has a gas cost that grows with the size of the input. In these cases, the test benchmarks the operation with a range of inputs to assess how the resource costs vary with different inputs.&lt;/p&gt;

&lt;h5 id=&quot;what-about-differences-between-client-implementations&quot;&gt;What about differences between client implementations?&lt;/h5&gt;

&lt;p&gt;Ultimately, we require a single cost model that is independent of the client’s implementation. Although the decision may be different in a specific situation, the general rule is to take the worst client result that cannot be optimized. This means that the worst-performing client on a given operation and resource combination defines the cost of that operation for the entire network. This is the safer and most conservative choice, and it is the value reported in the table above.&lt;/p&gt;

&lt;h4 id=&quot;runtime-estimation&quot;&gt;Runtime Estimation&lt;/h4&gt;

&lt;p&gt;To estimate the runtime of a single operation from the total execution time of the corresponding synthetic blocks, a &lt;strong&gt;Non-Negative Least Squares (NNLS) Linear Regression&lt;/strong&gt; is used. This model enforces that all coefficients are non-negative, thus ensuring execution time cannot be negative. The model estimates runtime as a linear combination of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Constant term (intercept)&lt;/strong&gt;: Base overhead for executing the test, which includes setup and teardown time&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Operation count (slope)&lt;/strong&gt;: Number of times the operation is executed in the test. This parameter is the one that allows us to estimate the per-operation runtime.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Operation-specific parameters&lt;/strong&gt;: Variables like number of rounds, message size, or number of pairs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For simple operations (i.e., without additional parameters), the model estimates: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtime = intercept + slope × operation_count&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For variable operations, the model estimates: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtime = intercept + slope × operation_count + param1_coef × operation_count × param1 + param2_coef × operation_count × param2 + ...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Independent models are created for each client and operation. Only operations and parameters with good model fits (R² &amp;gt; 0.5 and p-value &amp;lt; 0.05) are relied upon for the conclusion, to ensure the reliability of the estimates.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;/assets/eip-7904/analysis/2026-06-10/runtime_estimation_autogenerated_report&quot;&gt;model-performance report&lt;/a&gt; breaks down the fit by operation and client, while the &lt;a href=&quot;/assets/eip-7904/analysis/2026-06-10/results.csv&quot;&gt;key model outputs&lt;/a&gt; are available as a CSV.&lt;/p&gt;

&lt;h4 id=&quot;conversion-to-gas-costs&quot;&gt;Conversion to gas costs&lt;/h4&gt;

&lt;p&gt;The measured gas costs in the table are calculated using the target performance of 100 Mgas/s. The formula used is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gas = (anchor_rate * runtime_ms) / 1000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtime_ms&lt;/code&gt; is the estimated runtime in milliseconds from the regression models and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchor_rate&lt;/code&gt; is 100 Mgas/s.&lt;/p&gt;

&lt;p&gt;The full details of this step are in the &lt;a href=&quot;/assets/eip-7904/analysis/2026-06-10/new_gas_proposal&quot;&gt;proposal report&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;other-projects&quot;&gt;Other Projects&lt;/h3&gt;

&lt;p&gt;Several initiatives have explored the real gas costs of EVM operations, providing valuable context for this analysis. Notable examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;a href=&quot;/assets/eip-7904/gas-cost-estimator-report.pdf&quot;&gt;Gas Cost Estimator&lt;/a&gt; project did a similar empirical analysis. It conducted extensive testing across seven widely-used EVM implementations to measure the actual computational effort required by various opcodes and operations. Conducted in a controlled environment to eliminate external variables, the tests produced accurate and reproducible results. The findings highlight the relationship between the current gas cost schedule and the real-world computational complexity of EVM operations.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/EIPS/eip-7883&quot;&gt;EIP-7883&lt;/a&gt; - ModExp Gas Cost Increase: This EIP specifically analyzed ModExp and proposed a revised pricing scheme, consistent with the measuring approach used here.&lt;/li&gt;
  &lt;li&gt;Nethermind’s Gas Benchmarks: This project takes a different approach to measuring gas costs. It uses standalone clients rather than isolated EVM implementations. Despite the methodological difference, its results mirror those of the Gas Cost Estimator, reinforcing our conclusions.&lt;/li&gt;
  &lt;li&gt;EVM Memory Analysis by @raxhvl: This project focuses on memory-related costs, providing valuable insights into the memory access and expansion costs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These projects collectively provide context for reassessing gas costs and demonstrate broad alignment with our measurements.&lt;/p&gt;

&lt;h3 id=&quot;interaction-with-eip-7928&quot;&gt;Interaction with &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; introduces Block-Level Access Lists, which enable parallel disk reads, parallel transaction validation, and executionless state updates through client optimizations. The latest benchmarks were run on clients that have these optimizations implemented and stabilized. This is the central reason the analysis reaches a no-repricing conclusion: with the optimizations in place, the compute operations previously identified as bottlenecks now clear the target throughput at their current gas costs.&lt;/p&gt;

&lt;h3 id=&quot;computational-complexity-only&quot;&gt;Computational Complexity Only&lt;/h3&gt;

&lt;p&gt;This analysis intentionally focuses on computational complexity—measured as execution time on a bare CPU — while excluding network-related costs like state persistency. This ensures the findings remain implementation-agnostic, applicable across diverse EVM clients regardless of their technological stack. By leveraging empirical data from multiple EVM implementations, we establish a universal, verifiable benchmark for computational effort. This focus simplifies estimation and enhances the analysis’s clarity and applicability within Ethereum’s varied ecosystem.&lt;/p&gt;

&lt;h3 id=&quot;why-no-repricing-is-recommended&quot;&gt;Why No Repricing Is Recommended&lt;/h3&gt;

&lt;p&gt;The original proposal adopted a conservative strategy: prioritize gas increases only for operations that empirical data showed as underpriced, so that the base throughput of the chain could be raised without changing the costs of the majority of operations. Applying that same standard to the latest data yields no candidates for repricing — the measured runtimes of all examined operations are consistent with, or cheaper than, their current gas costs at the 100 Mgas/s target. Lowering gas costs is out of scope for this analysis, which was concerned only with identifying and removing underpriced bottlenecks. Consequently, the gas schedule is left unchanged.&lt;/p&gt;

&lt;h3 id=&quot;consideration-of-zk-snark-proof-generation&quot;&gt;Consideration of ZK-SNARK Proof Generation&lt;/h3&gt;

&lt;p&gt;This analysis focuses on general computational complexity, using a bare CPU as the reference point. Therefore, it does not specifically address the unique demands of ZK-SNARK proof generation. Since the analysis recommends no gas-cost changes, it has no effect on proving times for EVM blocks.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;This is an Informational EIP that recommends no changes to the Ethereum protocol or gas schedule. It introduces no consensus changes and therefore no direct security implications.&lt;/p&gt;

&lt;p&gt;The analysis itself is conservative: it relies on the worst-performing client for each operation and only draws conclusions from regression models with good statistical fits. Should client performance characteristics change in the future — for example, if an optimization is reverted or a new operation is introduced — the analysis should be re-run before relying on its conclusion that the current compute gas costs are adequate.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Wed, 05 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7904</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7904</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Block-Level Access Lists</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7928 - Block-Level Access Lists&lt;/strong&gt; is in Last Call status. It is authored by Toni Wahrstätter (@nerolation), Dankrad Feist (@dankrad), Francesco D`Amato (@fradamt), Jochem Brouwer (@jochem-brouwer), Ignacio Hagopian (@jsign), Felipe Selmo (@fselmo), Rahul (@raxhvl), Stefan (@qu0b) and was originally created 2025-03-31. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7928-block-level-access-lists/23337&quot;&gt;https://ethereum-magicians.org/t/eip-7928-block-level-access-lists/23337&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP introduces Block-Level Access Lists (BALs) that record all accounts and storage locations accessed during block execution, along with their post-execution values. BALs enable parallel disk reads, parallel transaction validation, parallel state root computation and executionless state updates.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Transaction execution cannot be parallelized without knowing in advance which addresses and storage slots will be accessed. While &lt;a href=&quot;/EIPS/eip-2930&quot;&gt;EIP-2930&lt;/a&gt; introduced optional transaction access lists, they are not enforced.&lt;/p&gt;

&lt;p&gt;This proposal enforces access lists at the block level, enabling:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Parallel disk reads and transaction execution&lt;/li&gt;
  &lt;li&gt;Parallel post-state root calculation&lt;/li&gt;
  &lt;li&gt;State reconstruction without executing transactions&lt;/li&gt;
  &lt;li&gt;Reduced execution time to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parallel IO + parallel EVM&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;block-structure-modification&quot;&gt;Block Structure Modification&lt;/h3&gt;

&lt;p&gt;We introduce a new field to the block header, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_access_list_hash&lt;/code&gt;, which contains the Keccak-256 hash of the RLP-encoded block access list. For an empty block access list, this is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(rlp.encode([])) = 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Existing fields
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;block_access_list_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Hash32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_access_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockAccessList&lt;/code&gt; is not included in the block body. The EL stores BALs separately and transmits them as a field in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayload&lt;/code&gt; via the engine API. The BAL is RLP-encoded as a list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AccountChanges&lt;/code&gt;. An empty block access list encodes as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xc0&lt;/code&gt;, i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rlp.encode([])&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;rlp-data-structures&quot;&gt;RLP Data Structures&lt;/h3&gt;

&lt;p&gt;BALs use RLP encoding following the pattern: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address -&amp;gt; field -&amp;gt; block_access_index -&amp;gt; change&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Type aliases for RLP encoding
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes20&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 20-byte Ethereum address
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StorageKey&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint256&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Storage slot key
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StorageValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint256&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Storage value
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bytecode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Variable-length contract bytecode
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BlockAccessIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint32&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Block access index (0 for pre-execution, 1..n for transactions, n+1 for post-execution)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Balance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint256&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Post-transaction balance in wei
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Nonce&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint64&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Account nonce
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Core change structures (RLP encoded as lists)
# StorageChange: [block_access_index, new_value]
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StorageChange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BlockAccessIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StorageValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# BalanceChange: [block_access_index, post_balance]
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BalanceChange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BlockAccessIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Balance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# NonceChange: [block_access_index, new_nonce]
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NonceChange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BlockAccessIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# CodeChange: [block_access_index, new_code]
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CodeChange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BlockAccessIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bytecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# SlotChanges: [slot, [changes]]
# All changes to a single storage slot
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SlotChanges&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StorageKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StorageChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# AccountChanges: [address, storage_changes, storage_reads, balance_changes, nonce_changes, code_changes]
# All changes for a single account, grouped by field type
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AccountChanges&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;                    &lt;span class=&quot;c1&quot;&gt;# address
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SlotChanges&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# storage_changes (slot -&amp;gt; [block_access_index -&amp;gt; new_value])
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StorageKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;# storage_reads (read-only storage keys)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BalanceChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# balance_changes ([block_access_index -&amp;gt; post_balance])
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NonceChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# nonce_changes ([block_access_index -&amp;gt; new_nonce])
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CodeChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# code_changes ([block_access_index -&amp;gt; new_code])
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# BlockAccessList: List of AccountChanges
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BlockAccessList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AccountChanges&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;scope-and-inclusion&quot;&gt;Scope and Inclusion&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockAccessList&lt;/code&gt;&lt;/strong&gt; is the set of all addresses accessed during block execution.&lt;/p&gt;

&lt;p&gt;It MUST include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Addresses with state changes (storage, balance, nonce, or code).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Addresses accessed without state changes, including:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;Targets of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BALANCE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODEHASH&lt;/code&gt; opcodes&lt;/li&gt;
      &lt;li&gt;Targets of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALLCODE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DELEGATECALL&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATICCALL&lt;/code&gt; (even if they revert; see &lt;a href=&quot;#gas-validation-before-state-access&quot;&gt;Gas Validation Before State Access&lt;/a&gt; for inclusion conditions)&lt;/li&gt;
      &lt;li&gt;Target addresses of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; only once the EVM accesses the computed address: on post-access out-of-gas, on creation collision, or when creation setup increments the new account’s nonce; not on address computation alone, nor when creation fails before access (e.g. insufficient sender balance for the endowment, nonce overflow, or call stack depth limit)&lt;/li&gt;
      &lt;li&gt;Deployed contract addresses from creation transactions, i.e. transactions with an empty &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to&lt;/code&gt; field, which are always included since the deployment address is unconditionally accessed during transaction setup&lt;/li&gt;
      &lt;li&gt;Transaction sender and recipient addresses (even for zero-value transfers), unless the transaction halts before the recipient is loaded (see &lt;strong&gt;Exceptional halts&lt;/strong&gt;)&lt;/li&gt;
      &lt;li&gt;Beneficiary addresses for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;System contract addresses accessed during pre/post-execution; the system caller address, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSTEM_ADDRESS&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xfffffffffffffffffffffffffffffffffffffffe&lt;/code&gt;), MUST NOT be included unless it experiences state access itself&lt;/li&gt;
      &lt;li&gt;Withdrawal recipient addresses, regardless of whether the withdrawal amount is non-zero&lt;/li&gt;
      &lt;li&gt;Precompiled contracts when called or accessed&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Addresses with no state changes MUST still be present with empty change lists.&lt;/p&gt;

&lt;p&gt;Entries from an &lt;a href=&quot;/EIPS/eip-2930&quot;&gt;EIP-2930&lt;/a&gt; access list MUST NOT be included automatically. Only addresses and storage slots that are actually touched or changed during execution are recorded.&lt;/p&gt;

&lt;h3 id=&quot;block-access-list-size-constraint&quot;&gt;Block Access List Size Constraint&lt;/h3&gt;

&lt;p&gt;The block access list is constrained by the block gas limit rather than a fixed maximum number of items. The constraint is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bal_items &amp;lt;= block_gas_limit // ITEM_COST
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bal_items = storage_keys + addresses&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITEM_COST = 2000&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_keys&lt;/code&gt; is the total number of storage keys across all accounts, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addresses&lt;/code&gt; is the total number of unique addresses accessed in the block. With &lt;a href=&quot;/EIPS/eip-7981&quot;&gt;EIP-7981&lt;/a&gt;, the cheapest way to add an item to the BAL is a cold &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOAD&lt;/code&gt; at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_SLOAD_COST&lt;/code&gt; (2100, as defined in &lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt;). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITEM_COST&lt;/code&gt; is set deliberately below this minimum to create a buffer of approximately &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_gas_limit / 42000&lt;/code&gt; extra items, which absorbs BAL entries from system contract execution (e.g., &lt;a href=&quot;/EIPS/eip-2935&quot;&gt;EIP-2935&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-4788&quot;&gt;EIP-4788&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-7251&quot;&gt;EIP-7251&lt;/a&gt;) and withdrawal recipients (&lt;a href=&quot;/EIPS/eip-4895&quot;&gt;EIP-4895&lt;/a&gt;) that do not consume block gas.&lt;/p&gt;

&lt;h3 id=&quot;gas-validation-before-state-access&quot;&gt;Gas Validation Before State Access&lt;/h3&gt;

&lt;p&gt;State-accessing opcodes perform gas validation in two phases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Pre-state validation&lt;/strong&gt;: Gas costs determinable without state access (memory expansion, base opcode cost, warm/cold access cost)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Post-state validation&lt;/strong&gt;: Gas costs requiring state access (account existence, &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; delegation resolution)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pre-state validation MUST pass before any state access occurs. If pre-state validation fails, the target resource (address or storage slot) is never accessed and MUST NOT be included in the BAL.&lt;/p&gt;

&lt;p&gt;Once pre-state validation passes, the target is accessed and included in the BAL. Post-state costs are then calculated; their order is implementation-defined since the target has already been accessed.&lt;/p&gt;

&lt;p&gt;The following table specifies pre-state validation costs in addition to the base opcode cost (gas constants as defined in &lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt;):&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Instruction&lt;/th&gt;
      &lt;th&gt;Pre-state Validation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BALANCE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFBALANCE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;None (accesses current contract, always warm)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODEHASH&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory_expansion&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_COPY&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory_expansion&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CALL_VALUE&lt;/code&gt; (if value &amp;gt; 0)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALLCODE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory_expansion&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CALL_VALUE&lt;/code&gt; (if value &amp;gt; 0)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DELEGATECALL&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory_expansion&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATICCALL&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory_expansion&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory_expansion&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INITCODE_WORD_COST&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory_expansion&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INITCODE_WORD_COST&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_KECCAK256_WORD&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOAD&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt;, and more than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CALL_STIPEND&lt;/code&gt; available&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_SELF_DESTRUCT&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt;: For account-accessing opcodes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS_COST&lt;/code&gt; if cold and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_STORAGE_READ_COST&lt;/code&gt; if warm, except for a warm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; beneficiary, which has zero access cost as specified by &lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt;. For storage-accessing opcodes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOAD&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt;), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_SLOAD_COST&lt;/code&gt; if cold and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_STORAGE_READ_COST&lt;/code&gt; if warm.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory_expansion&lt;/code&gt;: Gas cost to expand memory for input/output regions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Post-state costs (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; for calls to empty accounts, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_SELF_DESTRUCT_NEW_ACCOUNT&lt;/code&gt; if beneficiary does not exist) do not affect BAL inclusion since the target has already been accessed.&lt;/p&gt;

&lt;h4 id=&quot;eip-7702-delegation&quot;&gt;EIP-7702 Delegation&lt;/h4&gt;

&lt;p&gt;When a call target has an &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; delegation, the target is accessed to resolve the delegation, which also accesses the delegated address. The delegated address requires its own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt; check before being accessed; if that gas check fails, the delegated address MUST NOT appear in the BAL. Otherwise both the original call target and the delegated address MUST appear in the BAL, including when the call subsequently fails its sender-balance (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender_balance &amp;gt;= value&lt;/code&gt;) or call-stack-depth check, since the delegation is resolved before those checks.&lt;/p&gt;

&lt;p&gt;Note: Delegated accounts cannot be empty, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; never applies when resolving delegations.&lt;/p&gt;

&lt;h4 id=&quot;sstore&quot;&gt;SSTORE&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; performs an implicit read of the current storage value for gas calculation. Before this read, the frame MUST cover the storage slot’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_cost&lt;/code&gt; and MUST also satisfy the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CALL_STIPEND&lt;/code&gt; sentry (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left &amp;gt; GAS_CALL_STIPEND&lt;/code&gt;); because the access cost can exceed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CALL_STIPEND&lt;/code&gt; after repricing, the stipend sentry alone is no longer sufficient. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; fails this check, the storage slot MUST NOT appear in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_reads&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_changes&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;ordering-uniqueness-and-determinism&quot;&gt;Ordering, Uniqueness and Determinism&lt;/h3&gt;

&lt;p&gt;The following ordering rules MUST apply:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Accounts&lt;/strong&gt;: Lexicographic by address&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;storage_changes&lt;/strong&gt;: Slots by storage key value (ascending); within each slot, changes by block access index (ascending)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;storage_reads&lt;/strong&gt;: By storage key value (ascending)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;balance_changes, nonce_changes, code_changes&lt;/strong&gt;: By block access index (ascending)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following uniqueness constraints MUST hold:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Each address MUST appear exactly once in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockAccessList&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Each storage key MUST appear at most once in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_changes&lt;/code&gt; per account.&lt;/li&gt;
  &lt;li&gt;Each storage key MUST appear at most once in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_reads&lt;/code&gt; per account.&lt;/li&gt;
  &lt;li&gt;A storage key MUST NOT appear in both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_changes&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_reads&lt;/code&gt; for the same account.&lt;/li&gt;
  &lt;li&gt;Each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_access_index&lt;/code&gt; MUST appear at most once per change list (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;balance_changes&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce_changes&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code_changes&lt;/code&gt;, and per-slot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StorageChange&lt;/code&gt; list).&lt;/li&gt;
  &lt;li&gt;Each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SlotChanges&lt;/code&gt; entry MUST contain at least one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StorageChange&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;blockaccessindex-assignment&quot;&gt;BlockAccessIndex Assignment&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockAccessIndex&lt;/code&gt; values MUST be assigned as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; for &lt;strong&gt;pre‑execution&lt;/strong&gt; system contract calls.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 … n&lt;/code&gt; for transactions (in block order).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n + 1&lt;/code&gt; for &lt;strong&gt;post‑execution&lt;/strong&gt; system contract calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;recording-semantics-by-change-type&quot;&gt;Recording Semantics by Change Type&lt;/h3&gt;

&lt;h4 id=&quot;storage&quot;&gt;Storage&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Writes include:&lt;/strong&gt;&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;Any value change (post‑value ≠ pre‑value).&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Zeroing&lt;/strong&gt; a slot (pre‑value exists, post‑value is zero).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Reads include:&lt;/strong&gt;&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;Slots accessed via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOAD&lt;/code&gt; that are not written.&lt;/li&gt;
      &lt;li&gt;Slots written with unchanged values (i.e., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; where post-value equals pre-value, also known as “no-op writes”).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: Implementations MUST compare each write against the storage value as of immediately before the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_access_index&lt;/code&gt; (i.e., the cumulative state from all prior indices, falling back to the pre-block state) to correctly distinguish between actual writes and no-op writes. A no-op write MUST NOT remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_changes&lt;/code&gt; entries from earlier indices for the same slot.&lt;/p&gt;

&lt;h4 id=&quot;balance-balance_changes&quot;&gt;Balance (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;balance_changes&lt;/code&gt;)&lt;/h4&gt;

&lt;p&gt;Record &lt;strong&gt;post‑transaction&lt;/strong&gt; balances (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt;) for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Transaction &lt;strong&gt;senders&lt;/strong&gt; (gas + value).&lt;/li&gt;
  &lt;li&gt;Transaction &lt;strong&gt;recipients&lt;/strong&gt; (only if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value &amp;gt; 0&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;CALL/CALLCODE &lt;strong&gt;senders&lt;/strong&gt; (value).&lt;/li&gt;
  &lt;li&gt;CALL/CALLCODE &lt;strong&gt;recipients&lt;/strong&gt; (only if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value &amp;gt; 0&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;CREATE/CREATE2 recipients (only if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value &amp;gt; 0&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;COINBASE&lt;/strong&gt; (rewards + fees).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SELFDESTRUCT/SENDALL&lt;/strong&gt; beneficiaries.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Withdrawal recipients&lt;/strong&gt; (system withdrawals, &lt;a href=&quot;/EIPS/eip-4895&quot;&gt;EIP-4895&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For unaltered account balances:&lt;/p&gt;

&lt;p&gt;If an account’s balance changes during a transaction, but its post-transaction balance is equal to its pre-transaction balance, then the change MUST NOT be recorded in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;balance_changes&lt;/code&gt;. The sender and recipient address MUST still be included in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AccountChanges&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following special cases require addresses to be included with empty changes if no other state changes occur:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Zero-value transfer recipients&lt;/li&gt;
  &lt;li&gt;Calling a same-transaction SELFDESTRUCT on an address that had a zero pre-transaction balance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A zero-value block reward MUST NOT trigger a balance change in the block access list and MUST NOT, by itself, cause the recipient address to be included. The recipient MUST still be included if it is accessed for other reasons (e.g., transaction fee accounting).&lt;/p&gt;

&lt;h4 id=&quot;code&quot;&gt;Code&lt;/h4&gt;

&lt;p&gt;Track &lt;strong&gt;post‑transaction runtime bytecode&lt;/strong&gt; for deployed or modified contracts, and &lt;strong&gt;delegation indicators&lt;/strong&gt; for successful delegations as defined in &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;nonce&quot;&gt;Nonce&lt;/h4&gt;

&lt;p&gt;Record &lt;strong&gt;post‑transaction nonces&lt;/strong&gt; for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;EOA senders.&lt;/li&gt;
  &lt;li&gt;Contracts that performed a successful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Deployed contracts.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;edge-cases-normative&quot;&gt;Edge Cases (Normative)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;COINBASE / Fee Recipient:&lt;/strong&gt; The COINBASE address follows the same inclusion rules as any other account. It is included when accessed (e.g., during transaction fee accounting) and excluded when not accessed (e.g., empty blocks with no relevant withdrawals).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Precompiled contracts:&lt;/strong&gt; Precompiles MUST be included when accessed. If a precompile receives value, it is recorded with a balance change. Otherwise, it is included with empty change lists.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SENDALL:&lt;/strong&gt; For positive-value selfdestructs, the sender and beneficiary are recorded with a balance change.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SELFDESTRUCT (in-transaction):&lt;/strong&gt; Accounts destroyed within a transaction MUST be included in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AccountChanges&lt;/code&gt; without nonce or code changes. However, if the account had a positive balance pre-transaction, the balance change to zero MUST be recorded. Storage keys within the self-destructed contracts that were modified or read MUST be included as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_reads&lt;/code&gt; entry.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Accessed but unchanged:&lt;/strong&gt; Include the address with empty changes (e.g., targets of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODEHASH&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BALANCE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATICCALL&lt;/code&gt;, etc.).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Zero‑value transfers / Unchanged balance in transaction:&lt;/strong&gt; Include the address; omit from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;balance_changes&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Gas refunds:&lt;/strong&gt; Record the &lt;strong&gt;final&lt;/strong&gt; balance of the sender after each transaction.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Block rewards:&lt;/strong&gt; Record the &lt;strong&gt;final&lt;/strong&gt; balance of the fee recipient after each transaction.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Exceptional halts:&lt;/strong&gt; Record the &lt;strong&gt;final&lt;/strong&gt; nonce and balance of the sender, and the &lt;strong&gt;final&lt;/strong&gt; balance of the fee recipient after each transaction. State changes from the reverted call are discarded, but all accessed addresses MUST be included. If no changes remain, addresses are included with empty lists; if storage was read, the corresponding keys MUST appear in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_reads&lt;/code&gt;. A transaction can halt on a runtime gas charge before the recipient is loaded (e.g., during &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorization processing); the recipient is then never accessed and MUST NOT be included unless accessed for another reason.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Pre‑execution system contract calls:&lt;/strong&gt; All state changes MUST use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_access_index = 0&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Post‑execution system contract calls:&lt;/strong&gt; All state changes MUST use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_access_index = len(transactions) + 1&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EIP-7702 Delegations:&lt;/strong&gt; The authority address MUST be included with nonce and code changes after any successful delegation set, update, or clear. If authorization fails after the authority address has been loaded and added to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accessed_addresses&lt;/code&gt; (per &lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt;), it MUST still be included with an empty change set; if authorization fails before the authority is loaded, it MUST NOT be included. The delegation target MUST NOT be included during delegation creation or modification and MUST only be included once it is actually loaded as an execution target (e.g., via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALLCODE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DELEGATECALL&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATICCALL&lt;/code&gt; under authority execution).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EIP‑4895 (Consensus layer withdrawals):&lt;/strong&gt; Recipients are recorded with their final balance after the withdrawal.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EIP‑2935 (block hash):&lt;/strong&gt; Record system contract storage diffs of the &lt;strong&gt;single&lt;/strong&gt; updated storage slot in the ring buffer.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EIP‑4788 (beacon root):&lt;/strong&gt; Record system contract storage diffs of the &lt;strong&gt;two&lt;/strong&gt; updated storage slots in the ring buffer.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EIP‑7002 (withdrawals):&lt;/strong&gt; Record system contract storage diffs of storage slots &lt;strong&gt;0–3&lt;/strong&gt; (4 slots) after the dequeuing call. The dequeue also reads up to 3 × &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_WITHDRAWAL_REQUESTS_PER_BLOCK&lt;/code&gt; queue data slots (from slot 4 onward), which appear as storage_reads.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EIP‑7251 (consolidations):&lt;/strong&gt; Record system contract storage diffs of storage slots &lt;strong&gt;0–3&lt;/strong&gt; (4 slots) after the dequeuing call. The dequeue also reads up to 4 × &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_CONSOLIDATION_REQUESTS_PER_BLOCK&lt;/code&gt; queue data slots (from slot 4 onward), which appear as storage_reads.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;engine-api&quot;&gt;Engine API&lt;/h3&gt;

&lt;p&gt;The Engine API is extended with new structures and methods to support block-level access lists:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ExecutionPayloadV4&lt;/strong&gt; extends ExecutionPayloadV3 with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blockAccessList&lt;/code&gt;: RLP-encoded block access list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;engine_newPayloadV5&lt;/strong&gt; validates execution payloads:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Accepts &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadV4&lt;/code&gt; structure&lt;/li&gt;
  &lt;li&gt;Validates that computed access list matches provided &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blockAccessList&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INVALID&lt;/code&gt; if access list is malformed or doesn’t match&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;engine_getPayloadV6&lt;/strong&gt; builds execution payloads:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadV4&lt;/code&gt; structure&lt;/li&gt;
  &lt;li&gt;Collects all account accesses and state changes during transaction execution&lt;/li&gt;
  &lt;li&gt;Populates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blockAccessList&lt;/code&gt; field with RLP-encoded access list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Block processing flow:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When processing a block:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The EL receives the BAL in the ExecutionPayload&lt;/li&gt;
  &lt;li&gt;The EL computes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_access_list_hash = keccak256(blockAccessList)&lt;/code&gt; and includes it in the block header&lt;/li&gt;
  &lt;li&gt;The EL executes the block and generates the actual BAL&lt;/li&gt;
  &lt;li&gt;If the generated BAL doesn’t match the provided BAL, the block is invalid (the hash in the header would be wrong)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The execution layer provides the RLP-encoded &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blockAccessList&lt;/code&gt; to the consensus layer via the Engine API. The consensus layer stores it as a field in the SSZ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayload&lt;/code&gt; container. For long-term storage, the full &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blockAccessList&lt;/code&gt; bytes MAY be pruned and replaced by the field’s SSZ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hash_tree_root&lt;/code&gt;, preserving the Merkle commitment within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayload&lt;/code&gt; tree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retrieval methods&lt;/strong&gt; for historical BALs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_getPayloadBodiesByHashV2&lt;/code&gt;: Returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadBodyV2&lt;/code&gt; objects containing transactions, withdrawals, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blockAccessList&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_getPayloadBodiesByRangeV2&lt;/code&gt;: Returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayloadBodyV2&lt;/code&gt; objects containing transactions, withdrawals, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blockAccessList&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blockAccessList&lt;/code&gt; field contains the RLP-encoded BAL or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; for pre-Amsterdam blocks or when data has been pruned.&lt;/p&gt;

&lt;p&gt;The EL MUST retain BALs for at least the duration of the weak subjectivity period (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=3533 epochs&lt;/code&gt;) to support synchronization with re-execution after being offline for less than the WSP.&lt;/p&gt;

&lt;h3 id=&quot;state-transition-function&quot;&gt;State Transition Function&lt;/h3&gt;

&lt;p&gt;The state transition function must validate that the provided BAL matches the actual state accesses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation Note:&lt;/strong&gt; The BAL itself does not need to enter the state transition function. Implementations MAY validate by generating a virtual BAL during execution, hashing it, and comparing against the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_access_list_hash&lt;/code&gt; in the header. This is the approach used in the execution-specs reference implementation.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validate_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execution_payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 1. Compute hash from received BAL and set in header
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;block_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_access_list_hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keccak&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execution_payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blockAccessList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# 2. Execute block and collect actual accesses
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;actual_bal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;execute_and_collect_accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execution_payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# 3. Verify actual execution matches provided BAL
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# If this fails, the block is invalid (the hash in the header would be wrong)
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;actual_bal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;execution_payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blockAccessList&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;execute_and_collect_accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Execute block and collect all state accesses into BAL format&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Pre-execution system contracts (block_access_index = 0)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;track_system_contracts_pre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block_access_index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Execute transactions (block_access_index = 1..n)
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transactions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;execute_transaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;track_state_changes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block_access_index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Withdrawals and post-execution (block_access_index = len(txs) + 1)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;post_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transactions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;withdrawal&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;withdrawals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;apply_withdrawal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;withdrawal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;track_balance_change&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;withdrawal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;track_system_contracts_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Convert to BAL format and sort
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_bal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;track_state_changes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block_access_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Track all state changes from a transaction&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_touched_addresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&apos;storage_writes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# slot -&amp;gt; [(index, value)]
&lt;/span&gt;                &lt;span class=&quot;s&quot;&gt;&apos;storage_reads&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&apos;balance_changes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&apos;nonce_changes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&apos;code_changes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Track storage changes
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_storage_writes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;storage_writes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;storage_writes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;storage_writes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_access_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Track reads (slots accessed but not written)
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_storage_reads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;storage_writes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;storage_reads&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Track balance, nonce, code changes
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;balance_changed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;balance_changes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_access_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_balance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce_changed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;nonce_changes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_access_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code_changed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;code_changes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_access_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build_bal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Convert collected accesses to BAL format&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()):&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Sort addresses lexicographically
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accesses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Format storage changes: [slot, [[index, value], ...]]
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;storage_changes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;changes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt; 
                          &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;changes&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;storage_writes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())]&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Account entry: [address, storage_changes, reads, balance_changes, nonce_changes, code_changes]
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;bal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;storage_changes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;storage_reads&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])),&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;balance_changes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;nonce_changes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;code_changes&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The BAL MUST be complete and accurate. Missing or spurious entries invalidate the block. Spurious entries MAY be detected by validating BAL indices, which MUST never be higher than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;len(transactions) + 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Clients MAY invalidate immediately if any transaction exceeds declared state.&lt;/p&gt;

&lt;p&gt;Clients MUST store BALs separately from blocks and make them available via the engine API.&lt;/p&gt;

&lt;h3 id=&quot;concrete-example&quot;&gt;Concrete Example&lt;/h3&gt;

&lt;p&gt;Example block:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pre-execution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;EIP-2935: Store parent hash at block hash contract (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0000F90827F1C53a10cb7A02335B175320002935&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;EIP-7002: Omitted for simplicity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Transactions:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Alice (0xaaaa…) sends 1 ETH to Bob (0xbbbb…), checks balance of 0x2222…&lt;/li&gt;
  &lt;li&gt;Charlie (0xcccc…) calls factory (0xffff…) deploying contract at 0xdddd…&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Post-execution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Withdrawal of 100 ETH to Eve (0xabcd…)&lt;/li&gt;
  &lt;li&gt;EIP-7002 and EIP-7251 omitted for simplicity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: Pre-execution system contract uses block_access_index = 0. Post-execution withdrawal uses block_access_index = 3 (len(transactions) + 1)&lt;/p&gt;

&lt;p&gt;Resulting BAL (RLP structure):&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Addresses are sorted lexicographically
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# AccountChanges for 0x0000F90827F1C53a10cb7A02335B175320002935 (Block hash contract)
&lt;/span&gt;        &lt;span class=&quot;mh&quot;&gt;0x0000F90827F1C53a10cb7A02335B175320002935&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# storage_changes
&lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x00&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x0f\xa0&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;...&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# slot, [[block_access_index, parent_hash]]
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_reads
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# balance_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# nonce_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# code_changes
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# AccountChanges for 0x2222... (Address checked by Alice)
&lt;/span&gt;        &lt;span class=&quot;mh&quot;&gt;0x2222&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_reads
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# balance_changes (no change, just checked)
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# nonce_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# code_changes
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# AccountChanges for 0xaaaa... (Alice - sender tx 0)
&lt;/span&gt;        &lt;span class=&quot;mh&quot;&gt;0xaaaa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_reads
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;29&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a241a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# balance_changes: [[block_access_index, post_balance]]
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# nonce_changes: [[block_access_index, new_nonce]]
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# code_changes
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# AccountChanges for 0xabcd... (Eve - withdrawal recipient)
&lt;/span&gt;        &lt;span class=&quot;mh&quot;&gt;0xabcd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_reads
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f5e100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# balance_changes: 100 ETH withdrawal
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# nonce_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# code_changes
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# AccountChanges for 0xbbbb... (Bob - recipient tx 0)
&lt;/span&gt;        &lt;span class=&quot;mh&quot;&gt;0xbbbb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_reads
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b9aca00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# balance_changes: +1 ETH
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# nonce_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# code_changes
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# AccountChanges for 0xcccc... (Charlie - sender tx 1)
&lt;/span&gt;        &lt;span class=&quot;mh&quot;&gt;0xcccc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_reads
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bc16d67&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# balance_changes: after gas
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# nonce_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# code_changes
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# AccountChanges for 0xdddd... (Deployed contract)
&lt;/span&gt;        &lt;span class=&quot;mh&quot;&gt;0xdddd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_reads
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# balance_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# nonce_changes: new contract nonce
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x60\x80\x60\x40&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;...&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# code_changes: deployed bytecode
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# AccountChanges for 0xeeee... (COINBASE)
&lt;/span&gt;        &lt;span class=&quot;mh&quot;&gt;0xeeee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_reads
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;05&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f5e1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bebc2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# balance_changes: after tx fees
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# nonce_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# code_changes
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# AccountChanges for 0xffff... (Factory contract)
&lt;/span&gt;        &lt;span class=&quot;mh&quot;&gt;0xffff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# storage_changes
&lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x00&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x01&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x00&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xdd\xdd&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;...&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# slot 1, deployed address
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# storage_reads
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# balance_changes
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# nonce_changes: after CREATE
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# code_changes
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;RLP-encoded and compressed: ~400-500 bytes.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;bal-design-choice&quot;&gt;BAL Design Choice&lt;/h3&gt;

&lt;p&gt;This design variant was chosen for several key reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Size vs parallelization&lt;/strong&gt;: BALs include all accessed addresses (even unchanged) for complete parallel IO and execution.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Storage values for writes&lt;/strong&gt;: Post-execution values enable state reconstruction during sync without individual proofs against state root.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Overhead analysis&lt;/strong&gt;: Historical data shows ~90 KiB average BAL size.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Transaction independence&lt;/strong&gt;: 60-80% of transactions access disjoint storage slots, enabling effective parallelization. The remaining 20-40% can be parallelized by having post-transaction state diffs.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;RLP encoding&lt;/strong&gt;: Native Ethereum encoding format, maintains compatibility with existing infrastructure.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;bal-size-considerations-60m-block-gas-limit&quot;&gt;BAL Size Considerations (60m block gas limit)&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Average BAL size&lt;/strong&gt;: ~92.1 KiB (compressed)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Storage writes: ~36.1 KiB (39.2%)&lt;/li&gt;
  &lt;li&gt;Storage reads: ~25.8 KiB (28.0%)&lt;/li&gt;
  &lt;li&gt;Balance diffs: ~9.2 KiB (10.0%)&lt;/li&gt;
  &lt;li&gt;Nonce diffs: ~1.9 KiB (2.1%)&lt;/li&gt;
  &lt;li&gt;Code diffs: ~1.4 KiB (1.5%)&lt;/li&gt;
  &lt;li&gt;Account addresses (with diffs): ~12.5 KiB (13.6%)&lt;/li&gt;
  &lt;li&gt;Touched-only addresses: ~3.3 KiB (3.6%)&lt;/li&gt;
  &lt;li&gt;RLP encoding overhead: ~1.8 KiB (1.9%)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Smaller than current worst-case calldata blocks.&lt;/p&gt;

&lt;p&gt;An empirical analysis has been done &lt;a href=&quot;/assets/eip-7928/bal_size_analysis&quot;&gt;here&lt;/a&gt;. An updated analysis for a 60 million block gas limit can be found &lt;a href=&quot;/assets/eip-7928/bal_size_analysis_60m&quot;&gt;here&lt;/a&gt;, and a refreshed one over more recent blocks (October 2026) &lt;a href=&quot;/assets/eip-7928/bal_size_analysis_60m_2026_10&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;asynchronous-validation&quot;&gt;Asynchronous Validation&lt;/h3&gt;

&lt;p&gt;BAL verification occurs alongside parallel IO and EVM operations without delaying block processing.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This proposal requires changes to the block structure and engine API that are not backwards compatible and require a hard fork.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;validation-overhead&quot;&gt;Validation Overhead&lt;/h3&gt;

&lt;p&gt;Validating access lists and balance diffs adds validation overhead but is essential to prevent acceptance of invalid blocks.&lt;/p&gt;

&lt;h3 id=&quot;block-size&quot;&gt;Block Size&lt;/h3&gt;

&lt;p&gt;Increased block size impacts propagation but overhead (~70 KiB average) is reasonable for performance gains.&lt;/p&gt;

&lt;h3 id=&quot;spurious-storage-reads&quot;&gt;Spurious Storage Reads&lt;/h3&gt;

&lt;p&gt;Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_reads&lt;/code&gt; entries are not mapped to specific transaction indices, their validity can only be confirmed after executing all transactions. A malicious proposer could exploit this by declaring spurious storage reads that are never accessed, forcing clients into unnecessary I/O prefetching and data download while the block remains unrejectable until completion. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bal_items&lt;/code&gt; constraint bounds the number of such entries. Clients SHOULD additionally consider mechanisms to detect infeasible &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage_reads&lt;/code&gt; during execution and reject the block before it completes. Any such mechanism MUST NOT reject a valid block; in particular, the storage reads performed by system calls are not paid for by block gas and cannot be bounded by it.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Mon, 31 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7928</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7928</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Increase Maximum Contract Size</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7954 - Increase Maximum Contract Size&lt;/strong&gt; is in Last Call status. It is authored by Giulio Rebuffo (@Giulio2002), Ben Adams (@benaadams) and was originally created 2025-06-09. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/increase-maximum-contract-size-to-48kb/24509&quot;&gt;https://ethereum-magicians.org/t/increase-maximum-contract-size-to-48kb/24509&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP proposes to raise the maximum allowed size for contract code deployed on Ethereum from 24,576 bytes to 65,536 bytes, and to raise the initcode size limit from 49,152 bytes to 131,072 bytes.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;The current 24KiB contract size limit can be restrictive for complex contracts and applications. Increasing the limit to 64KiB allows for more feature-rich contracts while maintaining reasonable constraints on block and state growth.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Update the &lt;a href=&quot;/EIPS/eip-170&quot;&gt;EIP-170&lt;/a&gt; contract code size limit of 24KiB (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x6000&lt;/code&gt; bytes) to 64KiB (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x10000&lt;/code&gt; bytes).&lt;/li&gt;
  &lt;li&gt;Update the &lt;a href=&quot;/EIPS/eip-3860&quot;&gt;EIP-3860&lt;/a&gt; initcode size limit of 48KiB (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC000&lt;/code&gt; bytes) to 128KiB (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x20000&lt;/code&gt; bytes).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Developer Flexibility:&lt;/strong&gt; Enables more complex contracts and features.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Backward Compatibility:&lt;/strong&gt; Existing contracts are unaffected.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Simplicity:&lt;/strong&gt; Only the size limit is changed, with no other protocol modifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This change is not backwards compatible and must be activated via a network upgrade (hard fork). Contracts larger than 24KiB, up to 64KiB, will be deployable after activation.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;A higher contract size limit may marginally increase the risk of denial-of-service attacks via large contracts, but the new limit remains conservative.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Mon, 09 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7954</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7954</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>eth/70 - partial block receipt lists</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7975 - eth/70 - partial block receipt lists&lt;/strong&gt; is in Last Call status. It is authored by Felix Lange &lt;fjl@ethereum.org&gt;, Jochem Brouwer (@jochem-brouwer), Giulio Rebuffo (@Giulio2002) and was originally created 2025-06-16. It is in the Networking category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7975-eth-70-partial-block-receipt-lists/24658&quot;&gt;https://ethereum-magicians.org/t/eip-7975-eth-70-partial-block-receipt-lists/24658&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP modifies the ‘eth’ p2p protocol to allow requesting partial block receipt lists.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;As Ethereum moves toward a higher block gas limit on mainnet, the worst-case total size of
a block receipts list also becomes larger, and may eventually exceed the 10MiB message size
limit commonly applied in clients. This can lead to sync failures.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;Modify the encoding for receipts in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Receipts (0x10)&lt;/code&gt; message as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;(eth/69): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[request-id: P, [[receipt₁, receipt₂], ...]]&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(eth/70): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[request-id: P, lastBlockIncomplete: {0,1}, [[receipt₁, receipt₂], ...]]&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastBlockIncomplete&lt;/code&gt; flag is set to true (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;), the last receipt list does not
contain all receipts of the block, and the client will have to request the remaining
receipts of that block in a new request.&lt;/p&gt;

&lt;p&gt;To support such partial queries, we also modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetReceipts (0x0f)&lt;/code&gt; message:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;(eth/69): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[request-id: P, [blockhash₁: B_32, blockhash₂: B_32, ...]]&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(eth/70): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[request-id: P, firstBlockReceiptIndex: P, [blockhash₁: B_32, blockhash₂: B_32, ...]]&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the first block in the list of requested block hashes, the server shall omit receipts
up to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firstBlockReceiptIndex&lt;/code&gt; from the response.&lt;/p&gt;

&lt;p&gt;Downloading block receipts across multiple messages creates new attack surface. Partial
receipt lists cannot be verified against the block header, so in responses with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastBlockIncomplete = 1&lt;/code&gt;, the last receipts list must be validated in a different way:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Verify the total number of delivered receipts matches the count of transactions.&lt;/li&gt;
  &lt;li&gt;Verify the size of each receipt against the gas limit of the corresponding transaction,
i.e. reject if it is larger than gaslimit/8.&lt;/li&gt;
  &lt;li&gt;Verify the total downloaded receipts size is no larger than allowed by the block gas limit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;Since &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt; caps the gas limit of a single transaction to ~16.7M gas, a single
transaction receipt will always be limited in size. Specifically, a transaction can
produce at most 16777216/8 = 2MiB of log data.&lt;/p&gt;

&lt;p&gt;However, a block can contain multiple transactions, and thus the entire block
receipts list can be much larger. At a block gas limit of ~83M, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Receipts&lt;/code&gt; message
could exceed 10MiB. Clients typically reject messages above this size because their
validity can only be determined after fetching the complete message.&lt;/p&gt;

&lt;p&gt;For a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Receipts&lt;/code&gt; message, each block receipts list is validated by checking the full list
against the tree root stored in the block header. When downloading a paginated list across
multiple requests, the client must potentially buffer more than 10MB of unvalidated input.
This cannot be avoided, since the protocol allows receipt lists of such size at a high
block gas limit. However, we can at least bound the input size by applying sanity checks
as recommended in the specification section.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP changes the eth protocol and requires rolling out a new version, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/70&lt;/code&gt;.
Supporting multiple versions of a wire protocol is possible. Rolling out a new version
does not break older clients immediately, since they can keep using protocol version
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/69&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This EIP does not change consensus rules of the EVM and does not require a hard fork.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;None&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Mon, 16 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7975</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7975</guid>
      </item>
      
    
      
      
      <item>
        <title>Increase Calldata Floor Cost</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7976 - Increase Calldata Floor Cost&lt;/strong&gt; is in Last Call status. It is authored by Toni Wahrstätter (@nerolation) and was originally created 2025-06-18. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7976-further-increase-calldata-cost/24597&quot;&gt;https://ethereum-magicians.org/t/eip-7976-further-increase-calldata-cost/24597&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP proposes an adjustment to calldata pricing by raising the floor cost from 10/40 to 64/64 gas per calldata byte. This reduces the worst-case block size by ~37% with minimal impact.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;While &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt; successfully reduced the maximum possible block size by introducing a floor cost of 10/40 gas per byte for data-heavy transactions, continued increases in gas limit demands further optimization. The current floor cost still permits relatively large data-heavy payloads that contribute to block size variance. With 64/64 pricing, a 10 MiB uncompressed execution payload would require ~671M gas instead of ~105M gas under 10/40 pricing, providing significant headroom for gas limit increases.&lt;/p&gt;

&lt;p&gt;By increasing the floor cost to 64/64 gas per byte, this proposal aims to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Further reduce the maximum possible block size for data-heavy transactions&lt;/li&gt;
  &lt;li&gt;Create additional headroom for potential block gas limit increases&lt;/li&gt;
  &lt;li&gt;Maintain the same exemption for transactions with significant EVM computation&lt;/li&gt;
  &lt;li&gt;Have minimal impact on users&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Parameter&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STANDARD_TOKEN_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TOTAL_COST_FLOOR_PER_TOKEN&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;16&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tokens_in_calldata = zero_bytes_in_calldata + nonzero_bytes_in_calldata * 4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;floor_tokens_in_calldata = (zero_bytes_in_calldata + nonzero_bytes_in_calldata) * 4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Equivalently, the floor cost is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;64&lt;/code&gt; gas per calldata byte (both zero and non-zero), since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TOTAL_COST_FLOOR_PER_TOKEN * 4 = 64&lt;/code&gt;. The token abstraction is retained only for consistency with &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isContractCreation&lt;/code&gt; be a boolean indicating the respective event.&lt;/p&gt;

&lt;p&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_gas_used&lt;/code&gt; be the gas used for EVM execution with the gas refund subtracted.&lt;/p&gt;

&lt;p&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INITCODE_WORD_COST&lt;/code&gt; be 2 as defined in &lt;a href=&quot;/EIPS/eip-3860&quot;&gt;EIP-3860&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The formula for determining the gas used per transaction changes from &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt;’s implementation to:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gasUsed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;21000&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;STANDARD_TOKEN_COST&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokens_in_calldata&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;execution_gas_used&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isContractCreation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INITCODE_WORD_COST&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TOTAL_COST_FLOOR_PER_TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;floor_tokens_in_calldata&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Any transaction with a gas limit below &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21000 + TOTAL_COST_FLOOR_PER_TOKEN * floor_tokens_in_calldata&lt;/code&gt; or below its intrinsic gas cost (take the maximum of these two calculations) is considered invalid. This limitation exists because transactions must cover the floor price of their calldata without relying on the execution of the transaction. There are valid cases where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gasUsed&lt;/code&gt; will be below this floor price, but the floor price needs to be reserved in the transaction gas limit.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;With &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt;’s implementation, data-heavy transactions cost 10/40 gas per zero/non-zero byte, reducing the maximum possible EL payload size to approximately 1.07 MB (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;45_000_000/40&lt;/code&gt;). This EIP further reduces this to approximately 0.67 MB (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;45_000_000/64&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;By increasing calldata costs from 10/40 to 64/64 gas per byte for data-heavy transactions, this EIP provides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Enhanced block size reduction&lt;/strong&gt;: Maximum data-heavy payload size drops by ~37%.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Maintained user experience&lt;/strong&gt;: Regular users engaging in DeFi, token transfers, and other EVM-heavy operations remain unaffected&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Better blob incentivization&lt;/strong&gt;: Higher calldata costs further encourage migration to blob usage for data availability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The floor cost mechanism ensures that transactions involving significant EVM computation continue to pay the standard 4/16 gas per byte for calldata, preserving the user experience for regular Ethereum operations.&lt;/p&gt;

&lt;p&gt;Analyzing the block range 20644414 - 23272414 (Sept. 2024 - Sept. 2025), 1.5% of all transactions would have been affected.&lt;/p&gt;

&lt;p&gt;An empirical analysis summarizing the impact of this EIP can be found in &lt;a href=&quot;/assets/eip-7976/eip7976_empirical_analysis&quot;&gt;this&lt;/a&gt; report.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This is a backwards incompatible gas repricing that requires a scheduled network upgrade.&lt;/p&gt;

&lt;p&gt;Wallet developers and node operators MUST update gas estimation handling to accommodate the new calldata cost rules. Specifically:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Wallets&lt;/strong&gt;: Wallets using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth_estimateGas&lt;/code&gt; MUST be updated to ensure that they correctly account for the updated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TOTAL_COST_FLOOR_PER_TOKEN&lt;/code&gt; parameter of 16. Failure to do so could result in underestimating gas, leading to failed transactions.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Node Software&lt;/strong&gt;: RPC methods such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth_estimateGas&lt;/code&gt; MUST incorporate the updated formula for gas calculation with the new floor cost values.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Users can maintain their usual workflows without modification, as wallet and RPC updates will handle these changes.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Testing for this EIP should verify the correct application of the new calldata cost floor of 64/64 gas per byte:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Data-heavy transactions&lt;/strong&gt;: Verify transactions with minimal EVM execution pay the floor cost of 64 gas per calldata byte&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EVM-heavy transactions&lt;/strong&gt;: Confirm transactions with significant computation continue using standard 4/16 gas per byte&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Edge cases&lt;/strong&gt;: Test transactions at the boundary where execution gas equals or exceeds the floor cost&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Gas estimation&lt;/strong&gt;: Validate that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth_estimateGas&lt;/code&gt; correctly accounts for the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TOTAL_COST_FLOOR_PER_TOKEN&lt;/code&gt; value&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Invalid transactions&lt;/strong&gt;: Ensure transactions with insufficient gas limits are properly rejected&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;As the maximum possible block size is further reduced compared to &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt;, no additional security concerns are introduced beyond those already addressed in the original proposal.&lt;/p&gt;

&lt;p&gt;The same transaction bundling considerations from &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt; apply:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Transaction bundling was already possible and remains so&lt;/li&gt;
  &lt;li&gt;Bundling does not compromise the block size reduction objectives&lt;/li&gt;
  &lt;li&gt;Practical limitations (trust, coordination) continue to limit widespread bundling&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The increased floor cost strengthens the incentive structure for appropriate data availability method selection without introducing new attack vectors.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Wed, 18 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7976</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7976</guid>
      </item>
      
    
      
    
      
    
      
      
      <item>
        <title>Increase Access List Cost</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7981 - Increase Access List Cost&lt;/strong&gt; is in Last Call status. It is authored by Toni Wahrstätter (@nerolation) and was originally created 2024-12-27. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7981-increase-access-list-cost/24680&quot;&gt;https://ethereum-magicians.org/t/eip-7981-increase-access-list-cost/24680&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP charges access lists for their data footprint, preventing the circumvention of the &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt; floor pricing. This effectively reduces the worst-case block size by ~21% with minimal impact on users.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Access lists are only priced for storage but not for their data.&lt;/p&gt;

&lt;p&gt;Furthermore, access lists can circumvent the &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt; floor pricing by contributing to EVM gas while still leaving a non-negligible data footprint. This enables achieving the maximal possible block size by combining access lists with calldata at a certain ratio.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Parameter&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
      &lt;th&gt;Source&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCESS_LIST_ADDRESS_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2400&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;/EIPS/eip-2930&quot;&gt;EIP-2930&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCESS_LIST_STORAGE_KEY_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1900&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;/EIPS/eip-2930&quot;&gt;EIP-2930&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TOTAL_COST_FLOOR_PER_TOKEN&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;16&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;/EIPS/eip-7976&quot;&gt;EIP-7976&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_list_bytes&lt;/code&gt; be the total byte count of addresses (20 bytes each) and storage keys (32 bytes each) in the access list.&lt;/p&gt;

&lt;p&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_list_data_cost = 64 * access_list_bytes&lt;/code&gt; (i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1280&lt;/code&gt; gas per address and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2048&lt;/code&gt; gas per storage key). The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;64&lt;/code&gt; gas-per-byte rate matches the &lt;a href=&quot;/EIPS/eip-7976&quot;&gt;EIP-7976&lt;/a&gt; calldata floor.&lt;/p&gt;

&lt;p&gt;The access list data cost is added as a flat surcharge to the gas used calculation, leaving the &lt;a href=&quot;/EIPS/eip-2930&quot;&gt;EIP-2930&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_list_cost&lt;/code&gt; and the &lt;a href=&quot;/EIPS/eip-7976&quot;&gt;EIP-7976&lt;/a&gt; floor calculation unchanged:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gasUsed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;21000&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;access_list_data_cost&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;STANDARD_TOKEN_COST&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokens_in_calldata&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;execution_gas_used&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isContractCreation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INITCODE_WORD_COST&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;access_list_cost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TOTAL_COST_FLOOR_PER_TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;floor_tokens_in_calldata&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Any transaction with a gas limit below &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gasUsed&lt;/code&gt; evaluated with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_gas_used = 0&lt;/code&gt; is considered invalid.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;Access list data is always charged at floor rate (added to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access_list_cost&lt;/code&gt;), and access list tokens are included in the floor calculation. This ensures:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Access list data always pays floor rate regardless of execution level&lt;/li&gt;
  &lt;li&gt;Access lists cannot be used to bypass the calldata floor pricing&lt;/li&gt;
  &lt;li&gt;Consistent pricing across all transaction data sources&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This is a backwards incompatible gas repricing that requires a scheduled network upgrade.&lt;/p&gt;

&lt;p&gt;Requires updates to gas estimation in wallets and nodes. Normal usage patterns remain largely unaffected.&lt;/p&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculate_access_list_data_cost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;access_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;EIP-7981: flat 64 gas per byte of access list data.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Each access entry: 20-byte address + 32 bytes per storage key
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;total_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;access&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;access&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;access_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculate_intrinsic_cost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Calculate intrinsic gas cost and floor gas cost.
    Both include the EIP-7981 access list data surcharge, so that
    tx.gasUsed = max(intrinsic_gas + execution_gas_used, floor_gas).
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Calldata tokens (EIP-7976)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;zero_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count_zero_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nonzero_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zero_bytes&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tokens_in_calldata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zero_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonzero_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;floor_tokens_in_calldata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Access list cost (EIP-2930, unchanged) and EIP-7981 data surcharge
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;access_list_cost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;access_list_data_cost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has_access_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;access&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;access_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;access_list_cost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;ACCESS_LIST_ADDRESS_COST&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;access&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ACCESS_LIST_STORAGE_KEY_COST&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;access_list_data_cost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculate_access_list_data_cost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;access_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# EIP-7976 floor (calldata only) plus EIP-7981 surcharge
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;floor_gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TX_BASE_COST&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;floor_tokens_in_calldata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TOTAL_COST_FLOOR_PER_TOKEN&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;access_list_data_cost&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Intrinsic gas plus EIP-7981 surcharge
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;calldata_cost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokens_in_calldata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STANDARD_TOKEN_COST&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_cost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TX_CREATE_COST&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init_code_cost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;intrinsic_gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TX_BASE_COST&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calldata_cost&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_cost&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;access_list_cost&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;access_list_data_cost&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intrinsic_gas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;floor_gas&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;This EIP closes a loophole that allows circumventing &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt; floor pricing. Without this fix, attackers can achieve larger blocks than intended by combining access lists with calldata. All transaction data sources now contribute to the floor calculation consistently.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 27 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7981</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7981</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Deterministic Factory Contract</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7997 - Deterministic Factory Contract&lt;/strong&gt; is in Last Call status. It is authored by Francisco Giordano (@frangio), Toni Wahrstätter (@nerolation), Nick Johnson (@Arachnid), Jochem Brouwer (@jochem-brouwer) and was originally created 2025-08-03. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-7997-deterministic-factory-predeploy/24998&quot;&gt;https://ethereum-magicians.org/t/eip-7997-deterministic-factory-predeploy/24998&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;The availability of a well-known &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; factory at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4e59b44847b379578588920cA78FbF26c0B4956C&lt;/code&gt; is made a formal requirement to enable deterministic deployments at identical addresses across EVM chains. This benefits developer experience, user experience, and security, in particular for multi-chain and cross-chain applications, including account abstraction.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;There are now a large number of EVM chains where users want to transact and developers want to deploy applications, and we can expect this number to continue to grow in line with Ethereum’s rollup-centric roadmap and the general adoption of programmable blockchains. Most applications support multiple chains and aspire to support as many as possible, and their developers widely prefer to deploy contracts at identical addresses across all chains as a &lt;em&gt;multi-chain deterministic deployment&lt;/em&gt;. This kind of deployment reduces the number of addresses that must be distributed to use the application, so that it no longer scales with the number of supported chains. This simplification has many benefits throughout the stack: interfaces and SDKs need to embed and trust fewer addresses, and other contracts that depend on them can be implemented without chain-specific customization (which in turn makes them amenable to multi-chain deployment).&lt;/p&gt;

&lt;p&gt;This kind of deployment is also highly desirable and important for account abstraction. Without it, a user’s smart contract accounts are deployed at different addresses on different chains, and each account is tied to a single chain. This limitation is difficult to explain to users and has caused loss of funds. If smart contract accounts cannot be multi-chain like EOAs, they offer downgraded UX and are more prone to error.&lt;/p&gt;

&lt;p&gt;There is currently no native or fully robust way to perform multi-chain deterministic deployments. While &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; enables deterministic deployments, the created address is computed from that of the contract that invokes the instruction, so a &lt;em&gt;factory&lt;/em&gt; that is itself multi-chain is required for bootstrapping. Four workarounds are currently known to deploy such a factory:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A keyless transaction crafted using Nick’s method that can be posted permissionlessly to new chains.&lt;/li&gt;
  &lt;li&gt;Private keys held by some party used to sign creation transactions for each chain as needed.&lt;/li&gt;
  &lt;li&gt;A private key intentionally leaked so that any party can permissionlessly create an &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; signed delegation and deploy a factory from the leaked account.&lt;/li&gt;
  &lt;li&gt;Factories already deployed on other chains (by any of the previous methods) inserted in a new chain at genesis or via a hard fork.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keyless transactions have been the most successful approach. However, since such transactions have a fixed gas price and limit, they have often been impossible to deploy on chains where those gas parameters are insufficient or invalid. The same issue has begun to affect Ethereum itself and its devnets due to changes to the gas schedule. This EIP formalizes the guarantee that an already widely used keyless &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; factory should be available on EVM chains, whether deployed by an ordinary transaction (including its keyless transaction), or included in genesis.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FACTORY_ADDRESS&lt;/code&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4e59b44847b379578588920cA78FbF26c0B4956C&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The chain’s state MUST include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FACTORY_ADDRESS&lt;/code&gt; with nonzero nonce and this runtime code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A chain may satisfy this requirement by either of the following means that results in the account above: deploying the factory with an ordinary transaction (for example, its keyless creation transaction) where the chain’s gas parameters permit it, or including the account in the genesis state with a nonce equal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;. Regardless of the method used, the resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FACTORY_ADDRESS&lt;/code&gt; account MUST have the runtime code specified above. If the chain is already running with gas parameters that no longer allow deployment via the keyless transaction, the only way to add the contract at the expected address is a coordinated irregular state transition, which is outside the scope of this EIP. Client software MUST NOT check for the existence of the contract at the fork boundary.&lt;/p&gt;

&lt;p&gt;This is a contract that invokes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; instruction (&lt;a href=&quot;/EIPS/eip-1014&quot;&gt;EIP-1014&lt;/a&gt;) with a salt equal to the first 32 bytes of the call’s input data, init code equal to the remaining data, and value equal to the call’s value. If input data is smaller than 32 bytes, the contract will attempt to copy close to 2^256 bytes of calldata and should revert as a result. If contract creation fails (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; outputs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;), the call reverts with empty return data. When successful, the address is returned in exactly 20 bytes of data with no padding.&lt;/p&gt;

&lt;p&gt;The above runtime bytecode disassembles to the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-asm&quot;&gt;push32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0
calldatasize
add

push1 0x00
dup2
push1 0x20
dup3
calldatacopy

dup1
calldataload

dup3
dup3
callvalue
create2
dup1
iszero
iszero
push1 0x39
jumpi

dup2
dup3
revert

jumpdest
dup1
dup3
mstore
pop
pop
pop
push1 0x14
push1 0x0c
return
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;choice-of-factory&quot;&gt;Choice of factory&lt;/h3&gt;

&lt;p&gt;The factory at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4e59b44847b379578588920cA78FbF26c0B4956C&lt;/code&gt; has been used close to 25000 times on Ethereum Mainnet, deployed to hundreds of chains using its keyless transaction, included in multiple L2s by default, and used as the default factory for deterministic deployments in developer tools.&lt;/p&gt;

&lt;p&gt;The bytecode is compatible with any EVM chain that has activated EIP-1014, which Ethereum included in Constantinople. In particular, it does not depend on the more recent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUSH0&lt;/code&gt; (&lt;a href=&quot;/EIPS/eip-3855&quot;&gt;EIP-3855&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Two known downsides of this factory were considered. First, the address of the created account is returned with no padding, and may need to be decoded differently to other address-returning calls. Second, returndata is not propagated in case of revert, and an EVM trace may be required for obtaining a diagnostic error message. Both issues were considered non-blocking due to the existence of workarounds, including the possibility of using this factory to deploy further improved factories. Notably, if such factories are fully deterministic and permissionlessly deployable (and only require baseline EVM features), they are guaranteed to exist or be deployable at the same address on the same set of chains.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;No backwards compatibility issues are introduced. On chains that already have the factory at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FACTORY_ADDRESS&lt;/code&gt; (Ethereum Mainnet and most others), satisfying this requirement is a no-op. No other contract is expected at this address.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;frontrunnable-deployments&quot;&gt;Frontrunnable deployments&lt;/h3&gt;

&lt;p&gt;The deployment of contracts that read the environment (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ORIGIN&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NUMBER&lt;/code&gt;, etc.) may be frontrun and created with attacker-chosen parameters. It’s recommended to use this factory to deploy fully deterministic contracts only.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sun, 03 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7997</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7997</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Backward compatible SWAPN, DUPN, EXCHANGE</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8024 - Backward compatible SWAPN, DUPN, EXCHANGE&lt;/strong&gt; is in Last Call status. It is authored by Francisco Giordano (@frangio), Charles Cooper (@charles-cooper), Alex Beregszaszi (@axic), Paweł Bylica (@chfast) and was originally created 2025-08-16. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8024-backward-compatible-swapn-dupn-exchange/25486&quot;&gt;https://ethereum-magicians.org/t/eip-8024-backward-compatible-swapn-dupn-exchange/25486&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;Currently, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAP*&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUP*&lt;/code&gt; instructions are limited to a stack depth of 16. Introduce three new instructions, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAPN&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUPN&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE&lt;/code&gt; which lift this limitation and allow accessing the stack at higher depths.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;While the stack is 1024 items deep, easy access is only possible for the top 16 items. Supporting more local variables is possible via manually keeping them in memory or through a “stack to memory elevation” in a compiler. This can result in complex and inefficient code.&lt;/p&gt;

&lt;p&gt;Furthermore, implementing higher level constructs, such as functions, on top of EVM will result in a list of input and output parameters as well as an instruction offset to return to.&lt;/p&gt;

&lt;p&gt;The number of these arguments (or stack items) can easily exceed 16 and thus will require extra care from a compiler to lay them out in a way that all of them are still accessible.&lt;/p&gt;

&lt;p&gt;Lastly, swapping items besides the 1st and Nth items in the stack is very important for compilers implementing stack scheduling algorithms (the analog of register allocation for stack machines), which try to minimize stack traffic given a set of variables and usage analysis.&lt;/p&gt;

&lt;p&gt;Introducing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAPN&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUPN&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE&lt;/code&gt; will provide an option to compilers to simplify accessing deep stack items.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;We introduce three new instructions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUPN&lt;/code&gt;     (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xe6&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAPN&lt;/code&gt;    (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xe7&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xe8&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each instruction carries one or two immediate operands. Informally, using 1-based indexing, the semantics are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUPN n&lt;/code&gt;: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;‘th stack item is duplicated at the top of the stack.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAPN n&lt;/code&gt;: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n + 1&lt;/code&gt;‘th stack item is swapped with the top of the stack.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE n m&lt;/code&gt;: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n + 1&lt;/code&gt;‘th stack item is swapped with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m + 1&lt;/code&gt;‘th stack item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Formally, when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code[pc]&lt;/code&gt; is one of these opcodes, the VM executes as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUPN&lt;/code&gt;:
    &lt;ol&gt;
      &lt;li&gt;Charge 3 gas.&lt;/li&gt;
      &lt;li&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x = code[pc + 1]&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;90 &amp;lt; x &amp;lt; 128&lt;/code&gt;, halt with exceptional failure.&lt;/li&gt;
      &lt;li&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n = decode_single(x)&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n &amp;gt; len(stack)&lt;/code&gt;, halt with exceptional failure.&lt;/li&gt;
      &lt;li&gt;Push &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack[top - n + 1]&lt;/code&gt; on the stack.&lt;/li&gt;
      &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pc = pc + 2&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAPN&lt;/code&gt;:
    &lt;ol&gt;
      &lt;li&gt;Charge 3 gas.&lt;/li&gt;
      &lt;li&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x = code[pc + 1]&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;90 &amp;lt; x &amp;lt; 128&lt;/code&gt;, halt with exceptional failure.&lt;/li&gt;
      &lt;li&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n = decode_single(x)&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n + 1 &amp;gt; len(stack)&lt;/code&gt;, halt with exceptional failure.&lt;/li&gt;
      &lt;li&gt;Swap &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack[top - n]&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack[top]&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pc = pc + 2&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE&lt;/code&gt;:
    &lt;ol&gt;
      &lt;li&gt;Charge 3 gas.&lt;/li&gt;
      &lt;li&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x = code[pc + 1]&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;81 &amp;lt; x &amp;lt; 128&lt;/code&gt;, halt with exceptional failure.&lt;/li&gt;
      &lt;li&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n, m = decode_pair(x)&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m + 1 &amp;gt; len(stack)&lt;/code&gt;, halt with exceptional failure.&lt;/li&gt;
      &lt;li&gt;Swap &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack[top - n]&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack[top - m]&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pc = pc + 2&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code[pc + 1]&lt;/code&gt; evaluates to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; if beyond the end of the code, matching &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUSH&lt;/code&gt; behavior.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;top&lt;/code&gt; denotes the index of the value at the top of the stack.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JUMPDEST&lt;/code&gt; analysis is unchanged. In particular, if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code[i]&lt;/code&gt; is at an instruction boundary and is one of these opcodes, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code[i + 1]&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x5b&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JUMPDEST&lt;/code&gt;), then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code[i + 1]&lt;/code&gt; is a valid jump target. Note that in this case the execution of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code[i]&lt;/code&gt; would halt at step 2 above (because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x = code[i + 1] = 0x5b = 91&lt;/code&gt;). Disassemblers must decode such &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code[i]&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INVALID&lt;/code&gt; (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INVALID_DUPN&lt;/code&gt;, etc.) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code[i + 1]&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JUMPDEST&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The auxiliary functions &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decode_single&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decode_pair&lt;/code&gt; are defined by the following Python code:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;decode_single&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Returns n with 17 &amp;lt;= n &amp;lt;= 235.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;145&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;decode_pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Returns (n, m) with 1 &amp;lt;= n &amp;lt;= 14 and n &amp;lt; m &amp;lt;= 30 - n.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;81&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;143&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;divmod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;29&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Assemblers and compilers must emit a 1-byte immediate after each of these opcodes that decodes to the required &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n, m&lt;/code&gt; operands. For reference, this can be done by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encode_single&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encode_pair&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;encode_single&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;235&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;111&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;encode_pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;29&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;143&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;use-of-an-immediate-operand&quot;&gt;Use of an immediate operand&lt;/h3&gt;

&lt;p&gt;Allowing dynamic selection of the arguments to swap or dup could be used to prevent static analysis of the contents of the stack. Since static analysis is an important tool for security auditors we want to do what we can to make their jobs easier. Hence, the operands require an immediate operand that is not dynamic in nature.&lt;/p&gt;

&lt;h3 id=&quot;disallowed-immediate-range&quot;&gt;Disallowed immediate range&lt;/h3&gt;

&lt;p&gt;A property the EVM has is that it’s not possible to jump to the middle of an instruction. In order to guarantee this property, the immediate operands of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUSH*&lt;/code&gt; instructions are masked from jumpdest analysis so that the occurrence of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x5b&lt;/code&gt; in them is not mistaken for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JUMPDEST&lt;/code&gt; instruction, which should be considered a valid jump target elsewhere.&lt;/p&gt;

&lt;p&gt;The new instructions in this EIP preserve this property without changing jumpdest analysis by making it invalid for their immediates to contain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x5b&lt;/code&gt;, in addition to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x60&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x7f&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUSH1&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUSH32&lt;/code&gt;) since those would cause the subsequent instructions to be masked.&lt;/p&gt;

&lt;p&gt;The alternative, changing jumpdest analysis to introduce new masked opcodes, would create a backwards incompatibility if done without bytecode versioning (EOF). Consider the bytecode sequence &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e6 5b&lt;/code&gt; that decodes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INVALID JUMPDEST&lt;/code&gt; prior to this EIP, and thus contains a valid jump target. If an instruction &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUPN x&lt;/code&gt; were introduced with encoding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e6 {x}&lt;/code&gt; (opcode immediately followed by operand), and jumpdest analysis changed to mask the operand to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e6&lt;/code&gt;, the same bytecode sequence &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e6 5b&lt;/code&gt; would then decode to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUPN 0x5b&lt;/code&gt;. As a result of the upgrade, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5b&lt;/code&gt; would become an invalid jump target, breaking contracts that include this sequence. The opposite can happen with push opcodes, for example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e6 60 5b&lt;/code&gt; would transform from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INVALID PUSH1 0x5b&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUPN 0x60 JUMPDEST&lt;/code&gt;, creating a new valid jump target. Furthermore, this may have a cascading effect on arbitrarily many subsequent instructions.&lt;/p&gt;

&lt;p&gt;Since the EVM doesn’t offer a dedicated section for data, arbitrary data may be embedded in code and serve as immutable data storage accessed via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CODECOPY&lt;/code&gt;. Therefore, we must assume that arbitrary byte sequences may be found in contracts that have been deployed or are included in transactions yet to be published on chain.&lt;/p&gt;

&lt;p&gt;This EIP is designed to uphold the following backwards compatibility guarantee: every possible execution trace on a given bytecode that does not attempt to execute an undefined opcode must continue to produce the same effect after the introduction of an instruction. No new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JUMPDEST&lt;/code&gt;s must be created in a given bytecode by the introduction of an instruction and none may be removed.&lt;/p&gt;

&lt;p&gt;This encoding can be reused in future instructions with immediate operands, although it is not necessary if the range of the operand naturally does not include the bytes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x5b&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JUMPDEST&lt;/code&gt;) or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x60&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUSH1&lt;/code&gt;) to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x7f&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUSH32&lt;/code&gt;), in which case masking is not necessary.&lt;/p&gt;

&lt;h3 id=&quot;exchange-immediate&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE&lt;/code&gt; immediate&lt;/h3&gt;

&lt;p&gt;A previous formulation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE&lt;/code&gt; allowed swapping stack elements only if they were within some distance. As a result, it would be possible to swap the elements at indices 30 and 29, but not possible to move an element from index 30 to 2 with a single instruction. The current formulation prioritizes the latter, on the assumption that it is more valuable to move elements closer to the top of the stack than it is to rearrange elements deeper in the stack.&lt;/p&gt;

&lt;p&gt;In addition, the exact formulation was chosen to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decode_pair&lt;/code&gt; a simple function using only basic arithmetic, bitwise operations (division by 16), and few branches. A small trade-off in the number of addressable pairs was made to reduce the number of necessary branches; this implies some of the immediate range is not allocated, and it could be used to add a dozen more addressable pairs at the cost of more decoding complexity, potentially in a future network upgrade.&lt;/p&gt;

&lt;p&gt;Finally, note that the operands in the assembly instruction &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE n m&lt;/code&gt; appear “off by one”, i.e. it operates on the stack elements at depths &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n + 1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m + 1&lt;/code&gt;. These offsets were chosen to match the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAP&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAPN&lt;/code&gt; opcodes such that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE n m&lt;/code&gt; has an effect equivalent to the sequence &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAP{n} SWAP{m} SWAP{n}&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;size-of-immediate-operand&quot;&gt;Size of immediate operand&lt;/h3&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUPN&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAPN&lt;/code&gt; a 16-bit size was considered to accommodate the full stack space of 1024 items, however:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;that would require an additional restriction/check (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n &amp;lt; 1024&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;the 256 depth is a large improvement over the current 16 and the overhead of an extra byte would make it less useful&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Similarly for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE&lt;/code&gt;, the proposed scheme allows addressing of 30 items.&lt;/p&gt;

&lt;h3 id=&quot;gas-cost&quot;&gt;Gas cost&lt;/h3&gt;

&lt;p&gt;The gas cost for these operations is the same as for existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DUP*&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAP*&lt;/code&gt; instructions, because they are just implemented as pointer swaps and immediate decoding is negligible.&lt;/p&gt;

&lt;h3 id=&quot;exchange-vs-swapn&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAPN&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;As mentioned before, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXCHANGE&lt;/code&gt; is important to compilers implementing stack scheduling algorithms. Specifically, in the case that a stack item is scheduled to be consumed deeper in the stack (for instance, the 3rd item in the stack needs to be moved into 2nd position in order to be consumed by the next operation), that currently takes three instructions, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWAP2 SWAP3 SWAP2&lt;/code&gt;. However, in the EVM implementation, the implementation is just a pointer swap, so it could be implemented in a single instruction at no extra runtime cost to the client.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This has no effect on contracts that would never attempt to execute the opcodes allocated by this EIP. The jump targets of existing contracts are preserved.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;h3 id=&quot;assemblydisassembly&quot;&gt;Assembly/Disassembly&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e680&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[DUPN 17]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e7db&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[SWAPN 108]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e6805b&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[DUPN 17, JUMPDEST]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e75b&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[INVALID_SWAPN, JUMPDEST]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e6605b&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[INVALID_DUPN, PUSH1 0x5b]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e7610000&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[INVALID_SWAPN, PUSH2 0x0000]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e65f&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[INVALID_DUPN, PUSH0]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e89d&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[EXCHANGE 2 3]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e82f&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[EXCHANGE 1 19]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e850&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[EXCHANGE 14 16]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e851&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[EXCHANGE 14 15]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e852&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[INVALID_EXCHANGE, MSTORE]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;execution&quot;&gt;Execution&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;60016000808080808080808080808080808080e680&lt;/code&gt; results in 18 stack items, the top of the stack valued 1, the bottom of the stack valued 1, the rest valued 0&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;600160008080808080808080808080808080806002e780&lt;/code&gt; results in 18 stack items, the top of the stack valued 1, the bottom of the stack valued 2, the rest valued 0&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;600260008080808080600160008080808080808080e8&lt;/code&gt; at the end of code results in 17 stack items, the bottom of the stack valued 1, the 10th stack item from the top valued 2, the rest valued 0&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;600060016002e88e&lt;/code&gt; results in 3 stack items, from top to bottom: [2, 0, 1]&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;600080808080808080808080808080808080808080808080808080808060016002e88f&lt;/code&gt; results in 30 stack items, the top of the stack valued 2, the bottom of the stack valued 1, the rest valued 0&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e75b&lt;/code&gt; reverts&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;600456e65b&lt;/code&gt; executes successfully (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUSH 04 JUMP INVALID_DUPN JUMPDEST&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;60008080e88e15&lt;/code&gt; results in 3 stack items, the top of the stack valued 1, the rest valued 0&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e852&lt;/code&gt; reverts&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6000808080808080808080808080808080e680&lt;/code&gt; results in exceptional halt&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;The authors are not aware of any additional risks introduced here. The EVM stack is fixed at 1024 items and most implementations keep that in memory at all times. This change will increase the number of stack items accessible via single instruction.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sat, 16 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8024</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8024</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>State Creation Gas Cost Increase</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8037 - State Creation Gas Cost Increase&lt;/strong&gt; is in Last Call status. It is authored by Maria Silva (@misilva73), Carlos Perez (@CPerezz), Jochem Brouwer (@jochem-brouwer), Ansgar Dietrichs (@adietrichs), Łukasz Rozmej (@LukaszRozmej), Anders Elowsson (@anderselowsson), Francesco D&apos;Amato (@fradamt), Dragan Rakita (@rakita), Paweł Bylica (@chfast), Spencer Taylor-Brown (@spencer-tb), Gary Rong (@rjl493456442) and was originally created 2025-10-01. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8037-state-creation-gas-cost-increase/25694&quot;&gt;https://ethereum-magicians.org/t/eip-8037-state-creation-gas-cost-increase/25694&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This proposal increases the cost of state creation operations, thus avoiding excessive state growth under increased block gas limits. It introduces a new variable, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; (cost per state byte), and sets this unit of gas costs per new state byte by targeting an average state growth of 120 GiB per year at a reference block gas limit of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;150M&lt;/code&gt; gas units. It also introduces an independent metering for state creation costs, thus allowing for increased throughput and for larger contract deployments without being limited by the single transaction gas limit.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;State creation does not have a harmonized cost, with different methods incurring varied costs for creating the same size of new state. For instance, while contract deployment only costs ~200 gas units per new byte created, new storage slots cost ~313 gas units per new byte created. Also, deploying duplicated bytecode costs the same as deploying new bytecode, even though clients don’t store duplicated code in the database. This proposal establishes a standard to harmonize all state creation operations.&lt;/p&gt;

&lt;p&gt;Additionally, state growth will become a bottleneck for scaling under higher block limits. As of January 2026, the current database size in a Geth node dedicated to state is ~390 GiB. After the increase in gas limit from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;30M&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;60M&lt;/code&gt; gas units, the average size of new state created each day more than tripled, from ~105 MiB to ~326 MiB. This results in an annual growth of ~116 GiB.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/eip-8037/new_state_added.png&quot; alt=&quot;new_state_added&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The state-growth response we observe is not linear in the gas limit increase: a 2× bump (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;30M&lt;/code&gt; → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;60M&lt;/code&gt;) produced a roughly 3× jump in daily new state, suggesting a one-off shift in user behavior rather than a steady-state ratio. Treating the post-bump rate as the new baseline and extrapolating proportionally to the new gas limit, at a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;200M&lt;/code&gt; gas limit, the state would grow at a rate of ~387 GiB per year. Starting from 390 GiB, this rate would breach the 650 GiB threshold (at which point nodes begin experiencing performance degradation) in less than a year.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;new-parameters&quot;&gt;New parameters&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Parameter&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1530&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_STORAGE_SET&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;64&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;120&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_AUTH_BASE&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;23&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSTEM_MAX_SSTORES_PER_CALL&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;16&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_TOTAL_GAS_LIMIT&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;4,294,967,295 (2^32 - 1)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;parameter-changes&quot;&gt;Parameter changes&lt;/h3&gt;

&lt;p&gt;Upon activation of this EIP, the following parameters of the gas model are updated. The “New State Gas” column shows the state gas cost (charged to the state-gas dimension), while the “New Execution Gas” column shows additional execution gas costs that accompany the state gas charge.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Parameter&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Current&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;New State Gas&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;New Execution Gas&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Operations affected&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;32,000&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT x CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CODE_DEPOSIT&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;200/byte&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; per byte&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 × ceil(len/32)&lt;/code&gt; (hash cost)&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;25,000&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT x CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_STORAGE_SET&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;20,000&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_STORAGE_SET x CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_EMPTY_ACCOUNT_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;25,000&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT x CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;EOA delegation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_AUTH_BASE_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;12,500&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_AUTH_BASE x CPSB&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;EOA delegation&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt; is defined as the sum of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Calldata cost: 1,616 (101 bytes × 16), where 101 is the byte size of an &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorization tuple (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chain_id&lt;/code&gt; 8 + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address&lt;/code&gt; 20 + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt; 8 + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y_parity&lt;/code&gt; 1 + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; 32 + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt; 32). This is a representative size, not a worst case, since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chain_id&lt;/code&gt; is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt; and may exceed 8 bytes.&lt;/li&gt;
  &lt;li&gt;Recovering authority address (ecRecover): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PRECOMPILE_ECRECOVER&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Reading nonce and code of authority (cold access): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; (is updated by &lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Storing values in an already warm account: 2 x &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt; are defined and updated in &lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt;. The values are not yet final.&lt;/p&gt;

&lt;h3 id=&quot;multidimensional-metering-for-state-creation-costs&quot;&gt;Multidimensional metering for state creation costs&lt;/h3&gt;

&lt;p&gt;Besides the parameter changes, this proposal introduces an independent metering for state creation costs. Two gas dimensions are introduced, execution-gas and state-gas. For state creation operations, the “new state costs” are charged to state-gas, while the “new execution costs” are charged to execution-gas. The costs of all other operations are charged to execution-gas.&lt;/p&gt;

&lt;p&gt;At transaction level, the user pays for both execution-gas and state-gas. The total gas cost of a transaction is the sum of both dimensions. In addition, the transaction gas limit set in &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt; only applies to execution-gas, while state-gas is capped by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas&lt;/code&gt;, which this proposal in turn caps at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_TOTAL_GAS_LIMIT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At the block level, only the gas used in the bottleneck resource is considered when checking if the block is full and when updating the base fee for the next block. This gives a new meaning to the block’s gas limit and the block’s gas target: each now bounds the bottleneck resource (the dimension with the highest cumulative gas used) rather than a single combined gas counter.&lt;/p&gt;

&lt;h4 id=&quot;transaction-validation&quot;&gt;Transaction validation&lt;/h4&gt;

&lt;p&gt;Before transaction execution, inclusion of a transaction in a block requires that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The transaction’s &lt;strong&gt;gas limit is not higher than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_TOTAL_GAS_LIMIT&lt;/code&gt;&lt;/strong&gt;. Concretely, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas &amp;lt;= TX_MAX_TOTAL_GAS_LIMIT&lt;/code&gt;. Unlike &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_GAS_LIMIT&lt;/code&gt;, which this proposal applies to execution-gas only, this bound applies to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas&lt;/code&gt; as a whole and therefore to the sum of both dimensions.&lt;/li&gt;
  &lt;li&gt;The transaction’s &lt;strong&gt;intrinsic gas is not higher than &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt;’s transaction cap&lt;/strong&gt;. Concretely, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max(intrinsic_gas, calldata_floor_gas_cost) &amp;lt;= TX_MAX_GAS_LIMIT&lt;/code&gt;. Under &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intrinsic_gas&lt;/code&gt; is state-independent and charged entirely in execution-gas; there is no intrinsic state-gas component.&lt;/li&gt;
  &lt;li&gt;For each gas dimension, the &lt;strong&gt;cumulative gas used of all previous transactions added to the transaction’s contribution does not exceed the block gas limit&lt;/strong&gt;. Concretely, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;min(TX_MAX_GAS_LIMIT, tx.gas) &amp;lt;= execution_gas_available&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas &amp;lt;= state_gas_available&lt;/code&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_gas_available = block_env.block_gas_limit - block_output.block_execution_gas_used&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_available = block_env.block_gas_limit - block_output.block_state_gas_used&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This check is performed before transaction inclusion in a block.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intrinsic_gas&lt;/code&gt; is the state-independent intrinsic cost defined by &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;, charged entirely in execution-gas (base transaction cost, calldata, access lists, the recipient touch, value costs, and per-authorization base costs). It is the sole input to the transaction-validity check.&lt;/p&gt;

&lt;p&gt;All state-dependent charges — new account creation and &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; delegation costs — are no longer part of intrinsic gas. Per &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;, they are &lt;strong&gt;runtime charges&lt;/strong&gt; applied in the pre-execution phase, after the transaction is deemed valid but before the first EVM frame is entered.&lt;/p&gt;

&lt;h4 id=&quot;transaction-level-gas-accounting-reservoir-model&quot;&gt;Transaction-level gas accounting (reservoir model)&lt;/h4&gt;

&lt;p&gt;Since transactions have a single gas limit parameter (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas&lt;/code&gt;), gas accounting is enforced through a &lt;strong&gt;reservoir model&lt;/strong&gt;. The gas is split into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt;, and all gas counters are initialized, during the pre-execution phase defined by &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;. This phase occurs after the transaction has passed the intrinsic gas check but before the first EVM frame is entered.&lt;/p&gt;

&lt;p&gt;This EIP defines how the split and the counters are computed. The remaining accounting rules of the pre-execution phase (authorization processing, recipient warming, and the runtime account-creation and access charges) is specified in &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; are initialized as follows:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;evm_gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intrinsic_gas&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;execution_gas_budget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TX_MAX_GAS_LIMIT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intrinsic_gas&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gas_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execution_gas_budget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evm_gas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;state_gas_reservoir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evm_gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gas_left&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Because &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt; makes intrinsic gas state-independent, no state-gas component is subtracted from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas&lt;/code&gt; here and none is seeded into the reservoir. The state-dependent costs are applied as runtime charges — later in the pre-execution phase and during execution — drawing from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; first and from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; once the reservoir is exhausted.&lt;/p&gt;

&lt;p&gt;This means that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; holds gas that exceeds &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt;’s budget. Additionally, four new counters are introduced:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt; encodes the total state-gas used by the transaction, and it is initialized as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used = 0&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; encodes how much of the current frame’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; has been drawn for state-gas charges and not yet credited back (i.e., the state-gas not covered by the reservoir). Like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;, it is frame-local: it is initialized to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; at the start of each call frame and is used to refill state-gas in last-in, first-out (LIFO) order.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_baseline&lt;/code&gt; records the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; at the start of the state changes a frame’s rollback undoes, which for a call frame is its entry. Like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;, it is frame-local.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_committed&lt;/code&gt; records the part of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; that a frame’s rollback must not credit back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;, because the state it paid for is not rolled back. Like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;, it is frame-local. Only the top-level frame uses it; in other frames it is always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The gas counters operate as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Execution-gas charges deduct from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; only.&lt;/li&gt;
  &lt;li&gt;State-gas charges deduct from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; first. When the reservoir is exhausted, the remainder deducts from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; and increments &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; by that remainder. State-gas charges increment &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;If a state creation is undone during execution, the corresponding amount of state-gas is &lt;strong&gt;refilled in last-in, first-out (LIFO) order&lt;/strong&gt;: because charges deduct from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; first and from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; last, refills credit the pool charged last (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;) first. It is credited to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; first (decrementing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; by the same amount) up to the current value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt;, and any remainder is credited to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt;. State-gas refills decrement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt;. Throughout this specification, “refilling state-gas” refers to this LIFO operation.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; is passed to a child frame in full: the 63/64 rule applies to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; only. The parent keeps none of it while the child runs. On the child’s exit it becomes the parent’s again. Note: a refill in the child may have raised it above the amount passed in.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS&lt;/code&gt; opcode returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; only (excluding the reservoir).&lt;/li&gt;
  &lt;li&gt;State-gas is metered at the end of all state-mutating opcodes, call-frame boundaries (in case of exceptional halts and reverts) and at the end of the transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;gas-accounting-for-sstore-opcode-level&quot;&gt;Gas accounting for SSTORE (opcode-level)&lt;/h5&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Original value&lt;/th&gt;
      &lt;th&gt;Current value&lt;/th&gt;
      &lt;th&gt;New value&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
      &lt;th&gt;State-gas charges/refills&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;x&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Cleared slot, zero at transaction start&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_STORAGE_SET × CPSB&lt;/code&gt; refilled&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;x&lt;/td&gt;
      &lt;td&gt;New slot&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_STORAGE_SET × CPSB&lt;/code&gt; charged&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;x&lt;/td&gt;
      &lt;td&gt;x&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Cleared slot, non-zero at transaction start&lt;/td&gt;
      &lt;td&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;x&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;x&lt;/td&gt;
      &lt;td&gt;Cleared slot restored to its original non-zero value&lt;/td&gt;
      &lt;td&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;x or 0&lt;/td&gt;
      &lt;td&gt;y&lt;/td&gt;
      &lt;td&gt;z&lt;/td&gt;
      &lt;td&gt;All other writes to an existing slot&lt;/td&gt;
      &lt;td&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;State-gas accounting for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; is performed at the end of the opcode execution.&lt;/p&gt;

&lt;h5 id=&quot;gas-accounting-for-new-accounts&quot;&gt;Gas accounting for new accounts&lt;/h5&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Operation&lt;/th&gt;
      &lt;th&gt;State-gas charges/refills&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt; with value to non-existent account&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; charged&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; with bytecode size of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L&lt;/code&gt; to existent account&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L × CPSB&lt;/code&gt; charged&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; with bytecode size of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L&lt;/code&gt; to non-existent account&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(STATE_BYTES_PER_NEW_ACCOUNT + L) × CPSB&lt;/code&gt; charged&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; where balance transfer creates a new account&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; charged&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Here, an account is &lt;em&gt;existent&lt;/em&gt; if it already has a leaf in the state trie, i.e., it has a nonzero balance, a nonzero nonce, or non-empty code (per &lt;a href=&quot;/EIPS/eip-161&quot;&gt;EIP-161&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In particular, an address that holds a balance but has no code and a zero nonce is existent and is a valid &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; target under &lt;a href=&quot;/EIPS/eip-684&quot;&gt;EIP-684&lt;/a&gt;. Creating a contract at such an address updates the existing leaf rather than adding a new one, so only the code-deposit cost (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L × CPSB&lt;/code&gt;) applies and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; account-creation charge does not.&lt;/p&gt;

&lt;p&gt;State-gas accounting for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; operations is performed right before the respective call frame. In both families the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; account-creation charge is applied &lt;em&gt;conditionally&lt;/em&gt;: only when the operation is about to create a new account. The families differ only in &lt;em&gt;when&lt;/em&gt; the destination account may be read, which &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; constrains (see &lt;a href=&quot;#account-creation-charging-and-eip-7928&quot;&gt;Account-creation charging and EIP-7928&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt; family (conditional charge).&lt;/strong&gt; The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; account-creation charge is applied &lt;em&gt;conditionally&lt;/em&gt; right before entering the child frame: only when the target account does not exist and a positive value is transferred. If the operation is unsuccessful before entering the call frame (e.g., due to insufficient balance or due to the stack depth), or if the child frame reverts or halts exceptionally, the charged state-gas is refilled in LIFO order and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt; decreases by the same amount.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; family (conditional charge).&lt;/strong&gt; &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; defers reading the computed destination address until creation has passed the checks that precede any state access: sender balance for the endowment, nonce overflow, and the call-stack depth limit. A creation failing those checks never reads the destination, and no account-creation state-gas is charged. Once the checks pass, the destination is accessed — a single read that also performs the &lt;a href=&quot;/EIPS/eip-684&quot;&gt;EIP-684&lt;/a&gt; collision check:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If the destination is non-existent (per the existence rule above), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; is charged in the creating frame, before 63/64 of the remaining gas is forwarded: a portion drawn from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; reduces the gas forwarded to the create frame, and a failed charge exceptionally halts the creating frame — exactly as for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt;. If the destination pre-exists (e.g., it holds a balance), nothing is charged. The charge is decided by existence alone, independently of the collision outcome below.&lt;/li&gt;
  &lt;li&gt;On an address collision (&lt;a href=&quot;/EIPS/eip-684&quot;&gt;EIP-684&lt;/a&gt;) the creation fails as an exceptional halt of the create frame, consuming the forwarded gas. A colliding destination has a nonzero nonce or non-empty code, so it is existent and no account-creation state-gas was charged. A nonzero balance or non-empty storage alone does not cause a collision.&lt;/li&gt;
  &lt;li&gt;If the create frame reverts or halts exceptionally (including an address collision and a failed code deposit), the account creation is rolled back and any charged account-creation state-gas is refilled in LIFO order, decreasing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt; by the same amount — exactly as for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code-deposit portion (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L × CPSB&lt;/code&gt;) is unaffected by this rule and is charged at code-deposit time as usual.&lt;/p&gt;

&lt;p&gt;The same conditional rule applies to top-level contract-creation transactions. Under &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; account-creation charge is not part of intrinsic gas and is not reserved up front; it is applied as a runtime charge in the pre-execution phase, when transaction setup accesses the deployment address (an access &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; always records), only if the destination does not already exist. Like any other state charge, it draws from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; first and from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; once the reservoir is exhausted. If the transaction reverts or halts (including an address collision), any charged portion is undone by the frame’s rollback, and the unspent reservoir is returned to the sender by the normal end-of-transaction settlement.&lt;/p&gt;

&lt;p&gt;Charges for account creation with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; are charged at the point where it executes.&lt;/p&gt;

&lt;h5 id=&quot;gas-refills-for-selfdestruct&quot;&gt;Gas refills for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; for accounts created in the same transaction does not produce increases in state size as the account, its data and its storage is not included in the state trie. However, this operation does not produce any state-gas refills and there are no changes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For an account that existed before the transaction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; only transfers its balance and the account is not removed. Thus, no state-gas refill applies and no changes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt;. This is consistent with the behavior of &lt;a href=&quot;/EIPS/eip-6780&quot;&gt;EIP-6780&lt;/a&gt;.&lt;/p&gt;

&lt;h5 id=&quot;gas-accounting-for-halts-and-reverts&quot;&gt;Gas accounting for halts and reverts&lt;/h5&gt;

&lt;p&gt;A call frame’s state changes are rolled back on both reverts and exceptional halts. In both cases the frame’s state-gas is restored to its baseline rather than refilled:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;net_state_gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state_gas_baseline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state_gas_reservoir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state_gas_from_gas_left&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;evm_state_gas_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;net_state_gas&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gas_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state_gas_from_gas_left&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;state_gas_from_gas_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;state_gas_reservoir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state_gas_baseline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net_state_gas&lt;/code&gt; is negative for a frame that refilled more than it charged, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt; increases: the rollback also restores the state whose removal the refill credited. The restore assigns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; where a refill credits it, so it is applied before any refill its parent makes for the failed operation. The two cases differ only in how the frame’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; is treated, exactly as in existing EVM semantics.&lt;/p&gt;

&lt;p&gt;Only the top-level frame can have a baseline that is not its entry, and only when the transaction has &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorizations. Its rollback does not undo the authorizations applied in the pre-execution phase (&lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;), so the state-gas charged for them must not be refilled. The baseline is taken after the authorization charges and before the account-creation charge for the transaction’s target, so that charge is refilled. At this point the frame commits the state-gas charged so far:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;state_gas_committed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state_gas_from_gas_left&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;state_gas_baseline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state_gas_reservoir&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;state_gas_from_gas_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: A commit moves no gas and does not change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt;. It marks the state-gas as not refillable, so the rollback above does not credit it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the transaction fails before the top-level frame is entered, the pre-execution phase is rolled back, including the authorizations (&lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;). All state-gas charged in that phase is refilled: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_committed&lt;/code&gt; are both credited to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_baseline&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; are set back to the values they had at the start of the transaction.&lt;/p&gt;

&lt;p&gt;When a child frame &lt;strong&gt;succeeds&lt;/strong&gt;, its remaining &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; is returned to the parent and its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; is added to the parent’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; (the state-gas it funded from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; persists and is now backed by the merged &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;). Then, with the child’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; merged in, the frame returns state-gas to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;, up to the amount it has outstanding:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state_gas_reservoir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state_gas_from_gas_left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gas_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;state_gas_reservoir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;state_gas_from_gas_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: this undoes no state creation, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt; is unchanged. It only moves gas between the two pools.&lt;/p&gt;

&lt;p&gt;This step is needed because a refill may happen in a different frame than the matching charge. The original value in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; table above is the value at transaction start, not at frame entry. A frame may therefore clear a slot allocated by an earlier frame. Its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; may be smaller than the refill, and the rest goes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt;, although the charge drew from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;. The step moves it up on every merge, to the first frame with an outstanding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt;. If it reaches the top-level frame, it stays in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; and is returned to the sender by the end-of-transaction settlement.&lt;/p&gt;

&lt;p&gt;The step applies to successful children only. This requires that a frame that reverts or halts exceptionally returns no state-gas to its parent; the restore to the frame’s baseline above provides that. Otherwise the parent receives state-gas for a slot the rollback restored, and a later merge moves it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When a child frame &lt;strong&gt;reverts&lt;/strong&gt;, all of its state changes are rolled back, its state-gas is restored as above, and its resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; (including the credited &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt;) is returned to the parent.&lt;/p&gt;

&lt;p&gt;When a child frame &lt;strong&gt;halts exceptionally&lt;/strong&gt;, the same restore is applied, but the child’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; is consumed (set to zero) rather than returned, so the credited &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; is consumed with it.&lt;/p&gt;

&lt;p&gt;The same rules apply when the top-level call frame reverts or halts, treating the frame as a child of the transaction boundary. In particular, for address collisions in contract-creation transactions, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; is consumed in full. The colliding destination has a nonzero nonce or non-empty code (&lt;a href=&quot;/EIPS/eip-684&quot;&gt;EIP-684&lt;/a&gt;), so no account-creation state-gas was charged. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; is returned to the sender by the normal end-of-transaction settlement.&lt;/p&gt;

&lt;h5 id=&quot;gas-accounting-for-eip-7702-authorizations&quot;&gt;Gas accounting for &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorizations&lt;/h5&gt;

&lt;p&gt;Gas charges for &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorizations follow the specification in &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;pre-state-and-post-state-gas-validation&quot;&gt;Pre-state and post-state gas validation&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; defines two-phase gas validation for state-accessing opcodes: pre-state costs (determinable without state access) and post-state costs (requiring state access). Under this EIP, the execution-gas portion of these opcodes follows the &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; rules unchanged and is charged at opcode time against &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;. The state-gas portion is also charged at the opcode level, with the timing given for each opcode above.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CALL_STIPEND&lt;/code&gt; pre-state check (&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;) applies to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; only, excluding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;transaction-gas-used&quot;&gt;Transaction gas used&lt;/h4&gt;

&lt;p&gt;At the end of transaction execution, the gas used before and after refunds is defined as:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tx_gas_used_before_refund&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gas_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state_gas_reservoir&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tx_gas_refund&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx_gas_used_before_refund&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refund_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tx_gas_used_after_refund&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_gas_used_before_refund&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_gas_refund&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tx_gas_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx_gas_used_after_refund&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calldata_floor_gas_cost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The refund cap remains at 20% of gas used. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx_gas_used&lt;/code&gt; applies the &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt; calldata floor after refunds, so the floor can effectively negate part of a refund when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;calldata_floor_gas_cost &amp;gt; tx_gas_used_after_refund&lt;/code&gt;. The receipt &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cumulative_gas_used&lt;/code&gt; uses this post-floor value.&lt;/p&gt;

&lt;h4 id=&quot;block-level-gas-accounting&quot;&gt;Block-level gas accounting&lt;/h4&gt;

&lt;p&gt;At block level, instead of tracking a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_used&lt;/code&gt; counter, we keep track of two counters, one for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state-gas&lt;/code&gt; and one for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution-gas&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tx_state_gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evm_state_gas_used&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tx_execution_gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx_gas_used_after_refund&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_state_gas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calldata_floor_gas_cost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;block_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_execution_gas_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_execution_gas&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;block_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_state_gas_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_state_gas&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since all state-gas charges are now applied as runtime or execution-time charges (per &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;), the transaction’s total state-gas is fully captured by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt;; there is no separate intrinsic state-gas term to add.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt; calldata floor participates in block accounting through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max&lt;/code&gt; term, applied to the execution-gas dimension: calldata is an execution-gas resource, and the floor’s bound on worst-case block size holds only if a data-heavy transaction contributes at least the floor to the block’s gas accounting. The floor is compared against the transaction’s execution-gas portion alone — not the transaction total — so execution gas may absorb the floor exactly as under &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt;, while state-gas spending cannot (see &lt;a href=&quot;#calldata-floor-in-block-accounting&quot;&gt;Calldata floor in block accounting&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The block header &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_used&lt;/code&gt; field is set to:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;gas_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_execution_gas_used&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_state_gas_used&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The block validity condition uses this value:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gas_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gas_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;invalid block: too much gas used&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The base fee update rule is also modified accordingly:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;gas_used_delta&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gas_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gas_target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;integration-with-eip-7778&quot;&gt;Integration with &lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt;&lt;/h5&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt; excludes transaction refunds from block gas accounting. The refunds in question are those of the transaction refund counter — a execution-gas quantity. State-gas refills are not refunds in this sense: a refill reverses a charge for state that was never durably created (a reverted or exceptionally halted frame, a failed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;, or a slot set and reset within the same transaction), so the resource metered by the state-gas dimension was never consumed. Refills therefore remain netted into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_state_gas_used&lt;/code&gt; regardless of &lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt;, and only the execution-gas dimension changes (see &lt;a href=&quot;#state-gas-refills-under-eip-7778&quot;&gt;State-gas refills under EIP-7778&lt;/a&gt;). If implemented together with &lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt;, the block level would be updated to:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tx_state_gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evm_state_gas_used&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tx_execution_gas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx_gas_used_before_refund&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_state_gas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calldata_floor_gas_cost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;block_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_execution_gas_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_execution_gas&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;block_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block_state_gas_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx_state_gas&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max&lt;/code&gt; term preserves &lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt;’s block accounting rule &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.gas_used += max(tx_gas_used, calldata_floor_gas_cost)&lt;/code&gt;, applied here to the execution-gas dimension.&lt;/p&gt;

&lt;h4 id=&quot;receipt-semantics&quot;&gt;Receipt semantics&lt;/h4&gt;

&lt;p&gt;Receipt &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cumulative_gas_used&lt;/code&gt; tracks the cumulative sum of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx_gas_used&lt;/code&gt; (post-refund, post-floor) across transactions, instead of the block’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_used&lt;/code&gt;. This means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receipt[i].cumulative_gas_used - receipt[i-1].cumulative_gas_used&lt;/code&gt; equals the gas paid by transaction &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;system-contracts-and-system-transactions&quot;&gt;System contracts and system transactions&lt;/h3&gt;

&lt;p&gt;The gas limit of system contracts (e.g., &lt;a href=&quot;/EIPS/eip-2935&quot;&gt;EIP-2935&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-4788&quot;&gt;EIP-4788&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-7251&quot;&gt;EIP-7251&lt;/a&gt;) that are invoked at the start of every block via a system call is updated from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;30M&lt;/code&gt; to:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;SYSTEM_CALL_GAS_LIMIT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30_000_000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STATE_BYTES_PER_STORAGE_SET&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;×&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CPSB&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;×&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SYSTEM_MAX_SSTORES_PER_CALL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This ensures preservation of the existing execution margin for system contracts under higher state creation costs.&lt;/p&gt;

&lt;p&gt;Here, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSTEM_MAX_SSTORES_PER_CALL = 16&lt;/code&gt; is the upper bound on the number of new storage slots a single system call is expected to write. It is a margin rather than a bound derived from any particular system contract, and must be re-derived if a system call can write more new slots.&lt;/p&gt;

&lt;p&gt;The additional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_STORAGE_SET × CPSB × SYSTEM_MAX_SSTORES_PER_CALL&lt;/code&gt; is placed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; while the rest of the system call’s gas is placed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;. System calls remain not subject to the &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_GAS_LIMIT&lt;/code&gt; cap, do not count against the block gas limit, and do not contribute to either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_execution_gas_used&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_state_gas_used&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;deriving-the-cost-per-state-byte-cpsb&quot;&gt;Deriving the cost per state byte (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt;)&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; is a fixed parameter derived from a reference block gas limit. The derivation pins the cost so that, at the reference block gas limit and under expected average utilization, total state growth stays at the target rate. If a future block gas limit increase materially changes the expected state growth rate, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; can be re-derived in a subsequent EIP.&lt;/p&gt;

&lt;h4 id=&quot;inputs&quot;&gt;Inputs&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Target state growth&lt;/strong&gt;: 120 GiB per year, i.e., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;120 × 2^30 = 128,849,018,880&lt;/code&gt; bytes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Reference block gas limit&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;150M&lt;/code&gt; gas units.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Slot time&lt;/strong&gt;: 12 seconds, giving &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;86400 / 12 = 7,200&lt;/code&gt; blocks per day and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7,200 × 365 = 2,628,000&lt;/code&gt; blocks per year.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Average state-gas utilization&lt;/strong&gt;: 50% of the block gas limit. Under multidimensional metering, the base fee converges to the target, which is half of the gas limit. On average, half of each block’s gas budget can therefore be consumed by state-gas charges before the base fee starts pushing back.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;derivation&quot;&gt;Derivation&lt;/h4&gt;

&lt;p&gt;The total state gas available for state creation in a year is:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;total_state_gas_per_year = (gas_limit / 2) × blocks_per_year
                         = (150,000,000 / 2) × 2,628,000
                         = 75,000,000 × 2,628,000
                         = 1.971 × 10^14 gas
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dividing by the target byte count gives the cost per state byte:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CPSB = total_state_gas_per_year / target_state_growth
     = 1.971 × 10^14 / 128,849,018,880
     ≈ 1530 gas/byte
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;why-target-a-150m-block-limit&quot;&gt;Why target a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;150M&lt;/code&gt; block limit?&lt;/h4&gt;

&lt;p&gt;The reference block gas limit of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;150M&lt;/code&gt; is chosen as a middle ground between the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;60M&lt;/code&gt; and the expected future &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;300M&lt;/code&gt;. This allows us to set a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; that is not too high (which would cause a large immediate increase in state creation costs) nor too low (which would require a more aggressive increase in a future EIP when the block limit increases further).&lt;/p&gt;

&lt;p&gt;With this target, we expect state growth will slow down significantly compared to the current trajectory and then increase again as we slowly increase the block gas limit.&lt;/p&gt;

&lt;h4 id=&quot;why-target-120-gib-per-year&quot;&gt;Why target 120 GiB per year?&lt;/h4&gt;

&lt;p&gt;By targeting a state growth of 120 GiB per year with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;150M&lt;/code&gt; block limit, we achieve the following worst-case growth rate at different block limits:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Block limit&lt;/th&gt;
      &lt;th&gt;Worst-case growth rate&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100M&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;80 GiB/year&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;150M&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;120 GiB/year&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;200M&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;160 GiB/year&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;250M&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;200 GiB/year&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;300M&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;240 GiB/year&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;These rates are computed assuming blocks are fully utilized with state creation operations, which is a worst-case scenario. Assuming a smooth increase in block limit from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100M&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;300M&lt;/code&gt; over the next year, we would expect a worst-case average growth rate of around 160 GiB per year, which is a significant improvement over the current trajectory.&lt;/p&gt;

&lt;h3 id=&quot;harmonization-across-state-creation&quot;&gt;Harmonization across state creation&lt;/h3&gt;

&lt;p&gt;With the current pricing, the gas cost of creating 1 byte of state varies depending on the method used. The following table shows the various methods and their gas cost per byte. The calculation ignores the transaction intrinsic cost (21,000 gas units) and the costs of additional opcodes and scaffolding needed to execute such a transaction.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Method&lt;/th&gt;
      &lt;th&gt;What is written&lt;/th&gt;
      &lt;th&gt;Intrinsic gas&lt;/th&gt;
      &lt;th&gt;Bytes → state&lt;/th&gt;
      &lt;th&gt;Gas / byte&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Deploy 24 kB contract (&lt;a href=&quot;/EIPS/eip-170&quot;&gt;EIP-170&lt;/a&gt; limit)&lt;/td&gt;
      &lt;td&gt;Runtime code + account trie node&lt;/td&gt;
      &lt;td&gt;32,000 CREATE + 200 × 24,576 code deposit = 4,947,200 gas&lt;/td&gt;
      &lt;td&gt;24,696 B&lt;/td&gt;
      &lt;td&gt;~200 gas&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Fund fresh EOA with 1 wei&lt;/td&gt;
      &lt;td&gt;Updated account leaf&lt;/td&gt;
      &lt;td&gt;25,000 new account&lt;/td&gt;
      &lt;td&gt;~120 B&lt;/td&gt;
      &lt;td&gt;~208 gas&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Add delegate flag to funded EOA (&lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt;)&lt;/td&gt;
      &lt;td&gt;23 B (0xef0100‖address) + updated account leaf&lt;/td&gt;
      &lt;td&gt;25,000 PER_EMPTY_ACCOUNT + 12,500 PER_AUTH_BASE + 1,616 calldata - 7,823 refund = ~31,300 gas&lt;/td&gt;
      &lt;td&gt;~143 B&lt;/td&gt;
      &lt;td&gt;~219 gas&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorization to empty address&lt;/td&gt;
      &lt;td&gt;23 B (0xef0100‖address) + updated account leaf&lt;/td&gt;
      &lt;td&gt;25,000 PER_EMPTY_ACCOUNT + 12,500 PER_AUTH_BASE + 1,616 calldata = 39,116 gas&lt;/td&gt;
      &lt;td&gt;~143 B&lt;/td&gt;
      &lt;td&gt;~274 gas&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Fill new storage slots (SSTORE 0→x)&lt;/td&gt;
      &lt;td&gt;Slot in storage trie&lt;/td&gt;
      &lt;td&gt;20,000 gas/slot&lt;/td&gt;
      &lt;td&gt;64 B&lt;/td&gt;
      &lt;td&gt;~313 gas&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;To harmonize costs, we first set the gas cost of a single state byte, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt;, as explained above. Now that we have a standardized cost per byte, we can derive the various costs parameters by multiplying the unit cost by the increase in bytes any given operation creates in the database (i.e., 64 bytes per slot, 120 bytes per account and 23 bytes per authorization).&lt;/p&gt;

&lt;p&gt;Note that the fixed cost &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt; for contract deployments assumes the same cost as a new account creation.&lt;/p&gt;

&lt;h4 id=&quot;deriving-byte-size-for-new-slots-and-accounts&quot;&gt;Deriving byte size for new slots and accounts&lt;/h4&gt;

&lt;p&gt;The byte sizes used in this proposal correspond to the on-disk footprint of a new account or storage slot, taking into account both the leaf data and the key under which it is stored.&lt;/p&gt;

&lt;p&gt;A new account adds 120 bytes:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Field&lt;/th&gt;
      &lt;th&gt;Size&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Account hash (key)&lt;/td&gt;
      &lt;td&gt;32 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Nonce&lt;/td&gt;
      &lt;td&gt;8 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Balance&lt;/td&gt;
      &lt;td&gt;16 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Code hash&lt;/td&gt;
      &lt;td&gt;32 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Storage root&lt;/td&gt;
      &lt;td&gt;32 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;120 bytes&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;A new storage slot adds 64 bytes:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Field&lt;/th&gt;
      &lt;th&gt;Size&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Slot hash (key)&lt;/td&gt;
      &lt;td&gt;32 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Value&lt;/td&gt;
      &lt;td&gt;32 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;64 bytes&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;For &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorizations on an already-existing account, no new account leaf is created. The only new state written is the delegation indicator stored in the authority’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code&lt;/code&gt; field. As specified in &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt;, this indicator is the 3-byte magic prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xef0100&lt;/code&gt; concatenated with the 20-byte delegate address, for a total of 23 bytes:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Field&lt;/th&gt;
      &lt;th&gt;Size&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Delegation magic (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xef0100&lt;/code&gt;)&lt;/td&gt;
      &lt;td&gt;3 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Delegate address&lt;/td&gt;
      &lt;td&gt;20 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;23 bytes&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;When the authorization targets a non-existent account, the full &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT&lt;/code&gt; is charged in addition to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_AUTH_BASE&lt;/code&gt;, since both a new account leaf and the delegation indicator are written.&lt;/p&gt;

&lt;p&gt;These figures account only for the leaf payload and its keccak256 key. They do not include the additional trie overhead (intermediate nodes, encoding, etc.) incurred when the new entry is inserted. The values are therefore a lower bound on the actual state growth per operation.&lt;/p&gt;

&lt;h3 id=&quot;multidimensional-metering&quot;&gt;Multidimensional metering&lt;/h3&gt;

&lt;h4 id=&quot;eip-7825-limit-on-contract-size&quot;&gt;EIP-7825 limit on contract size&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt; introduces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_GAS_LIMIT&lt;/code&gt; (16.7M) as the maximum gas for a single transaction, in particular stipulating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas &amp;lt;= TX_MAX_GAS_LIMIT&lt;/code&gt; as a validity condition. Were we to continue enforcing this validity condition, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB = 1530&lt;/code&gt;, this proposal would limit the maximum contract size that can be deployed to roughly 7.5kB. Assuming a representative constructor execution budget of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5M&lt;/code&gt; execution gas on top of the 21,000 base transaction cost and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; account-creation cost, the remaining budget for code-deposit state gas yields $\frac{16,777,216 - 21,000 - 5,000,000 - 120 \times 1530}{1530} \approx 7{,}564$ bytes. This maximum size would only decrease if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; is re-derived upward in a future EIP.&lt;/p&gt;

&lt;p&gt;To solve this issue, we only apply this gas limit to execution gas, not state gas. Doing so does not weaken the intended scaling effect of &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt;, because execution gas meters all resources that benefit from parallelization. In particular, state growth does not: growing the state always requires writing to disk, an operation that can be parallelized, but crucially this part of the cost of a state growth operation has to be metered in execution gas, not state gas. In other words, any operation that grows the state should consume both execution gas and state gas, and the execution gas should fully account for all costs other than the long term effect of growing the state.&lt;/p&gt;

&lt;p&gt;However, we cannot statically enforce an execution gas consumption of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_GAS_LIMIT&lt;/code&gt;, while still allowing a higher state gas consumption, because transactions only have a single gas limit parameter, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas&lt;/code&gt;. This is solved through a &lt;strong&gt;reservoir model&lt;/strong&gt;: at transaction start, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evm_gas&lt;/code&gt; is split into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; (capped at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_GAS_LIMIT - intrinsic_gas&lt;/code&gt;) and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt; (the overflow). State gas charges draw from the reservoir first, then from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; when the reservoir is empty. Execution gas charges draw from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; only. Exceeding the execution gas budget behaves identically to running out of gas — no special error is needed.&lt;/p&gt;

&lt;p&gt;State-gas refills are applied in last-in, first-out (LIFO) order: because charges draw from the reservoir first and from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; last, refills credit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; first (up to the gas it borrowed, tracked by the frame-local &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; counter), then the reservoir. Undoing a state creation therefore restores the exact pools the charge drew from, as long as both happen in the same frame. Because the original value in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; table above is the value at transaction start rather than at frame entry, a refill may land in a frame other than the one that was charged; the counter is frame-local, so the gas then stays in the reservoir while the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; that funded the charge stays reduced. Returning it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; on the merge keeps the two pools from drifting into one another: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; is never inflated beyond &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_GAS_LIMIT - intrinsic_gas&lt;/code&gt;, and state-gas is not left in the reservoir while a frame is still owed it. The same mismatch is why LIFO order alone does not make a frame’s rollback correct: a frame may credit a refill it never funded, so rollback is specified as a restore to the frame’s baseline (see &lt;a href=&quot;#gas-accounting-for-halts-and-reverts&quot;&gt;Gas accounting for halts and reverts&lt;/a&gt;).&lt;/p&gt;

&lt;h4 id=&quot;keeping-an-absolute-transaction-gas-limit&quot;&gt;Keeping an absolute transaction gas limit&lt;/h4&gt;

&lt;p&gt;Applying &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt;’s cap to execution-gas alone would leave &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas&lt;/code&gt; itself bounded only by the block gas limit. That is not the intent of this proposal: a per-transaction gas limit is worth keeping. &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt; introduced one so that the work a single transaction can represent stays a small and predictable unit for proving, parallel execution, and scheduling, and so that this bound is fixed by the protocol rather than drifting upward with every block gas limit increase. This proposal raises that limit for the state dimension; it does not abolish it.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas&lt;/code&gt; is therefore capped at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_TOTAL_GAS_LIMIT&lt;/code&gt;, which keeps every transaction’s gas limit within an unsigned 32-bit integer. The bound is chosen to sit far above the deployments this proposal sets out to enable. Reusing the figures above (the 21,000 base transaction cost, a representative &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5M&lt;/code&gt; execution gas constructor budget, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; account-creation cost), the code-deposit budget it leaves is $\frac{2^{32} - 1 - 21,000 - 5,000,000 - 120 \times 1530}{1530} \approx 2{,}803{,}766$ bytes, roughly 2.8 MB and about 43 times &lt;a href=&quot;/EIPS/eip-7954&quot;&gt;EIP-7954&lt;/a&gt;’s 65,536-byte contract size limit, so a single transaction can still deploy dozens of maximum-size contracts. While the block gas limit stays below &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_TOTAL_GAS_LIMIT&lt;/code&gt;, the per-dimension block checks are the tighter bound and the cap rejects nothing that could be included today; what it adds is a ceiling that no later block gas limit increase can lift.&lt;/p&gt;

&lt;h4 id=&quot;higher-throughput&quot;&gt;Higher throughput&lt;/h4&gt;

&lt;p&gt;Another advantage of metering contract creation separately is that increasing the cost of state creation operation in line with the block limit will not affect the available gas for other operations. This allows for higher throughput.&lt;/p&gt;

&lt;h4 id=&quot;calldata-floor-in-block-accounting&quot;&gt;Calldata floor in block accounting&lt;/h4&gt;

&lt;p&gt;The &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt; calldata floor (raised further by &lt;a href=&quot;/EIPS/eip-7976&quot;&gt;EIP-7976&lt;/a&gt;) bounds worst-case block size only because it participates in block gas accounting: a data-heavy transaction must occupy at least the floor’s worth of the block gas limit, which is also what &lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt; preserves with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max(tx_gas_used, calldata_floor_gas_cost)&lt;/code&gt;. Omitting the floor from the two-dimensional accounting would let such a transaction pay the floor while contributing only its pre-floor gas to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_execution_gas_used&lt;/code&gt;, re-expanding the maximum bytes per block by the ratio of floor to standard calldata pricing and hiding the difference from the base-fee update. The transaction-validity check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max(intrinsic_gas, calldata_floor_gas_cost) &amp;lt;= TX_MAX_GAS_LIMIT&lt;/code&gt; does not provide this bound: it caps a single transaction’s calldata against the &lt;a href=&quot;/EIPS/eip-7825&quot;&gt;EIP-7825&lt;/a&gt; transaction limit but contributes nothing to the block’s cumulative counters, so a block could otherwise be filled with individually valid transactions whose floors were paid but never counted.&lt;/p&gt;

&lt;p&gt;The floor is compared against the transaction’s execution-gas portion (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx_gas_used_after_refund - tx_state_gas&lt;/code&gt;, or the before-refund equivalent under &lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt;) rather than the transaction total. This is the per-dimension restatement of &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt;’s existing rule, not a new restriction. Under single-dimensional accounting, gas spent on execution may absorb the floor, and this is sound because the absorbing gas occupies the very block budget the floor protects: with or without the floor binding, a transaction carrying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt; calldata bytes occupies at least the floor’s worth of block gas, which is the invariant that bounds bytes per block. Execution gas retains exactly this absorbing role here.&lt;/p&gt;

&lt;p&gt;What the per-dimension comparison rules out is absorption &lt;em&gt;across&lt;/em&gt; dimensions. State-gas occupies the state dimension’s separate budget, so under a transaction-total comparison (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max(tx_gas_used_after_refund, calldata_floor_gas_cost) - tx_state_gas&lt;/code&gt;) a transaction padded with state creation would enter its calldata into the execution dimension below the floor rate. The bytes-per-block bound would then no longer be a property of the execution dimension: it would hold only to the extent that the padding fills the state dimension, making the effective calldata bound a function of the state-gas schedule (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; and the per-item byte sizes) and silently weakening it whenever that schedule is re-derived. The per-dimension comparison keeps the bound unconditional and independent of state-gas pricing.&lt;/p&gt;

&lt;p&gt;A consequence of the per-dimension comparison is that the sum of a transaction’s block-accounted gas across dimensions can exceed the gas its sender pays; this is intentional — block accounting bounds resource consumption per dimension, while the payment rule remains the transaction-level floor of &lt;a href=&quot;/EIPS/eip-7623&quot;&gt;EIP-7623&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;state-gas-refills-under-eip-7778&quot;&gt;State-gas refills under &lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt; counts refunds toward block gas because a refund rebates work that was actually performed: a refunded &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; executed and its computational cost was real, so the rebate is an incentive, not evidence of less work. A state-gas refill is the opposite case. State-gas meters durable state growth, and a refill fires only when that growth is undone — the resource the dimension meters was never consumed. Counting gross (pre-refill) state-gas would make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_state_gas_used&lt;/code&gt; overstate actual state growth and invalidate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; derivation, which assumes the block’s state-gas approximates bytes written to state. There is no smuggling vector in excluding refills: the transient computation of rolled-back operations remains fully counted, since their execution-gas charges stay consumed and, under &lt;a href=&quot;/EIPS/eip-7778&quot;&gt;EIP-7778&lt;/a&gt;, are counted before refunds.&lt;/p&gt;

&lt;h3 id=&quot;account-creation-charging-and-eip-7928&quot;&gt;Account-creation charging and &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; (Block-Level Access Lists) constrains &lt;em&gt;when&lt;/em&gt; the target address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; may be accessed: only once the EVM reaches the computed address (on post-access out-of-gas, on creation collision, or when creation setup increments the new account’s nonce), and not on address computation alone, nor when creation fails before access (e.g., insufficient sender balance for the endowment, nonce overflow, or the call-stack depth limit).&lt;/p&gt;

&lt;p&gt;The conditional account-creation charge is compatible with this by construction. The existence read that decides the charge is the &lt;em&gt;same single access&lt;/em&gt; that performs the &lt;a href=&quot;/EIPS/eip-684&quot;&gt;EIP-684&lt;/a&gt; collision check, and it happens after the pre-access failure checks — exactly the access &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; already sanctions and records. Creations that fail before access charge nothing and appear nowhere in the block access list; creations that reach the access point are recorded and pay exactly for the state they are about to create. The recorded access set is identical to that of an unconditional-charge design: the charge decision introduces no additional read.&lt;/p&gt;

&lt;p&gt;An earlier revision of this EIP instead charged the account-creation portion unconditionally before the create frame (before the balance, nonce, and depth checks) and refilled it on frame exit when the destination pre-existed or creation failed. The conditional model was adopted because it removes the pre-existing-destination refill and the pre-access-failure refills (nothing was charged), aligns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt; family (state-dependent charges are applied when the state is read, conditionally on what is actually created), and avoids temporarily under-budgeting the create frame of a deployment onto a pre-existing account (e.g., a pre-funded deterministic-deployment address). The remaining refill — on failure of the create frame — is shared with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt;. At the transaction level the account-creation charge is not part of intrinsic gas at all: per &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt; it is a runtime charge, so transaction validity remains decidable without any state access while the charge is metered only when the state is actually accessed.&lt;/p&gt;

&lt;p&gt;Placement of the charge among the remaining alternatives:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Why not charge after the create frame exits?&lt;/strong&gt; Up to 63/64 of the parent’s execution gas is forwarded to the child, and deployment code may legitimately consume nearly all of it. Deferring the charge until the frame returns could make an otherwise-successful deployment fail with out-of-gas at frame exit, introducing semantic uncertainty.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Why not charge inside the create frame?&lt;/strong&gt; That would silently move the out-of-gas condition from the parent frame (the pre-existing behavior for account-creation charges) to the child frame. Charging in the creating frame, right after the destination access and before the 63/64 split, keeps the out-of-gas locus and the forwarded-gas computation identical to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt; family.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt; family the charge remains conditional and is unchanged: the callee is already resolved (including &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; delegation resolution) before the child frame, so there is no deferred-access conflict, and unconditionally pre-charging every call would create significant compatibility concerns (e.g., Solidity’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address.transfer()&lt;/code&gt; forwards no gas to the child frame).&lt;/p&gt;

&lt;p&gt;A remaining gap is value-bearing &lt;em&gt;normal transactions&lt;/em&gt; to an empty account, which trigger account creation but are not currently charged for it. This is addressed by &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;, which adds the account-creation cost to the intrinsic gas of such transactions (see &lt;a href=&quot;#pricing-mismatch-with-respect-to-eth-transfers&quot;&gt;Pricing mismatch with respect to ETH transfers&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This is a backwards-incompatible gas repricing that requires a scheduled network upgrade.&lt;/p&gt;

&lt;p&gt;Wallet developers and node operators MUST update gas estimation handling to accommodate the new state creation costs and the two-dimensional metering model. Specifically:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wallets: Wallets using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth_estimateGas&lt;/code&gt; MUST be updated to ensure they correctly account for the updated state creation costs and report &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas&lt;/code&gt; covering both the execution-gas and state-gas dimensions. Failure to do so could result in underestimating gas, leading to failed transactions.&lt;/li&gt;
  &lt;li&gt;Node Software: RPC methods such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth_estimateGas&lt;/code&gt; MUST incorporate the new state-gas charges, the reservoir-model accounting, and the two-dimensional block accounting when computing gas estimates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users can maintain their usual workflows without modification, as wallet and RPC updates will handle these changes.&lt;/p&gt;

&lt;p&gt;Contracts and tools measuring work as the difference between two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS&lt;/code&gt; reads can get a negative result. This EIP makes it possible both within a frame and across a call (see &lt;a href=&quot;#gas_left-can-increase&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; can increase&lt;/a&gt;). Contracts already deployed with such metering cannot be fixed.&lt;/p&gt;

&lt;h3 id=&quot;deterministic-deployment-factories&quot;&gt;Deterministic deployment factories&lt;/h3&gt;

&lt;p&gt;Some well-known deterministic deployment factories are deployed via pre-signed transactions with a hardcoded gas limit. The classic Nick’s method factory, for instance, uses a pre-signed transaction with a 100,000 gas limit. Under this EIP, the state creation cost of deploying these factories increases beyond their hardcoded gas limit, so the original pre-signed deployment transactions will no longer execute successfully. The same applies to other deterministic deployer contracts such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SingletonFactory&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Create2Deployer&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ImmutableCreate2Factory&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CreateX&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This does not affect existing networks where these factories are already deployed, including mainnet and L2s (which maintain their own gas schedules). The impact is limited to new networks (e.g., devnets and testnets) that activate this EIP from genesis and have not yet deployed these factories. On such networks, the pre-signed deployment transactions must be regenerated with an updated gas limit, or the factories must be pre-deployed at genesis. Tooling that relies on these factories being available at their canonical addresses SHOULD ensure they are deployed before use.&lt;/p&gt;

&lt;h3 id=&quot;estimated-price-impacts&quot;&gt;Estimated price impacts&lt;/h3&gt;

&lt;p&gt;Users and dApp developers will experience an increase in transaction costs associated with creating a new state. The next table summarizes the state-gas portion of state creation costs for common operations under the proposed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt; of 1,530. Additional execution-gas charges (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt;, hash cost) defined in &lt;a href=&quot;/EIPS/eip-8038&quot;&gt;EIP-8038&lt;/a&gt; apply on top.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Case&lt;/th&gt;
      &lt;th&gt;Current gas cost&lt;/th&gt;
      &lt;th&gt;Proposed gas cost&lt;/th&gt;
      &lt;th&gt;Gas cost increase&lt;/th&gt;
      &lt;th&gt;Proposed cost (ETH)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;New account&lt;/td&gt;
      &lt;td&gt;25,000&lt;/td&gt;
      &lt;td&gt;183,600&lt;/td&gt;
      &lt;td&gt;~7×&lt;/td&gt;
      &lt;td&gt;0.0000147&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;New slot&lt;/td&gt;
      &lt;td&gt;20,000&lt;/td&gt;
      &lt;td&gt;97,920&lt;/td&gt;
      &lt;td&gt;~5×&lt;/td&gt;
      &lt;td&gt;0.00000783&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;24 kB contract deployment&lt;/td&gt;
      &lt;td&gt;4,947,200&lt;/td&gt;
      &lt;td&gt;37,784,880&lt;/td&gt;
      &lt;td&gt;~8×&lt;/td&gt;
      &lt;td&gt;0.00302&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The “Proposed cost (ETH)” column assumes a base fee of 0.08 Gwei, which corresponds to the average base fee observed after the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;60M&lt;/code&gt; gas increase in December 2025 and January 2026.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;Increasing the cost of state creation operations could impact the usability of certain applications. More analysis is needed to understand the potential effects on various dApps and user behaviors.&lt;/p&gt;

&lt;h3 id=&quot;pricing-mismatch-with-respect-to-eth-transfers&quot;&gt;Pricing mismatch with respect to ETH transfers&lt;/h3&gt;

&lt;p&gt;One potential concern is the cost of creating a new account (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_NEW_ACCOUNT × CPSB&lt;/code&gt; gas units, e.g., 183,600 at the proposed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPSB&lt;/code&gt;), compared to transferring ETH to a fresh account (21,000 gas units). With this mismatch, users wishing to create a new account are incentivized to first send a normal transaction (costing 21,000) to this account to create it, thus avoiding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; charge.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt; solves this mismatch by adding a new component to the intrinsic gas cost of transactions. If a non-create transaction has value &amp;gt; 0 and targets a non-existent account, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; is added to intrinsic cost.&lt;/p&gt;

&lt;h3 id=&quot;added-complexity-in-block-building&quot;&gt;Added complexity in block building&lt;/h3&gt;

&lt;p&gt;Optimal block construction becomes more complex, since builders must now balance resource usage across multiple dimensions rather than a single gas metric. Sophisticated builders may gain an advantage by applying advanced optimization techniques, raising concerns about further builder centralization. However, practical heuristics (e.g., greedily filling blocks until one resource dimension saturates) remain effective for most use cases. These heuristics limit centralization pressure by keeping block construction feasible for local and less sophisticated builders.&lt;/p&gt;

&lt;h3 id=&quot;gas_left-can-increase&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; can increase&lt;/h3&gt;

&lt;p&gt;Refills credit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt;, so a frame’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; can be higher after an operation than before it. A contract measuring work as the difference between two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS&lt;/code&gt; reads then gets a negative value. This reverts under checked arithmetic and wraps under unchecked arithmetic.&lt;/p&gt;

&lt;p&gt;A negative result requires the charge to have drawn from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;, i.e. the reservoir to be empty. That is the case for every transaction with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.gas&lt;/code&gt; up to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX_MAX_GAS_LIMIT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is already possible in a single frame. Allocating a storage slot that was zero at transaction start and clearing it again refills &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATE_BYTES_PER_STORAGE_SET × CPSB&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE(k, 1); GAS; SSTORE(k, 0); GAS&lt;/code&gt; shows it: the two reads differ by the refill less the cost of the clear. Reads around both stores do not, because the charge and the refill cancel between them.&lt;/p&gt;

&lt;p&gt;Returning state-gas on a merge extends this across a call boundary, which no call does today. Metering a sub-call this way is the more common pattern. The amount is not limited to one slot: a merge returns up to the whole &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_from_gas_left&lt;/code&gt; the frame has accumulated. The bound is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left + state_gas_from_gas_left&lt;/code&gt; never exceeds the frame’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; at entry.&lt;/p&gt;

&lt;h3 id=&quot;interaction-with-erc-4337-bundles&quot;&gt;Interaction with &lt;a href=&quot;/EIPS/eip-4337&quot;&gt;ERC-4337&lt;/a&gt; bundles&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS&lt;/code&gt; opcode returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_left&lt;/code&gt; only and cannot observe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_gas_reservoir&lt;/code&gt;. Bundling protocols that meter sub-call consumption via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gasleft()&lt;/code&gt; deltas (e.g., the &lt;a href=&quot;/EIPS/eip-4337&quot;&gt;ERC-4337&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntryPoint&lt;/code&gt;) therefore cannot accurately attribute state-gas usage when it is funded by the reservoir. Because all user operations in a bundle share the transaction’s reservoir, one user operation’s state-gas refunds can subsidize another’s state-gas charges without appearing in either’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gasleft()&lt;/code&gt; delta. Bundlers and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntryPoint&lt;/code&gt; implementations MUST account for state-gas charges and refunds explicitly rather than relying on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gasleft()&lt;/code&gt; differences alone.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Wed, 01 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8037</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8037</guid>
      </item>
      
    
      
      
      <item>
        <title>State-access gas cost update</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8038 - State-access gas cost update&lt;/strong&gt; is in Last Call status. It is authored by Maria Silva (@misilva73), Wei Han Ng (@weiihann), Ansgar Dietrichs (@adietrichs) and was originally created 2025-10-03. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8038-state-access-gas-cost-update/25693&quot;&gt;https://ethereum-magicians.org/t/eip-8038-state-access-gas-cost-update/25693&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP updates the gas cost of state-access operations to reflect Ethereum’s larger state and the consequent slowdown of these operations. It dissects the cost of state-touching operations into three components — access, write, and state creation: the cold account access cost (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;) is raised, explicit write surcharges (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt;) are introduced, state-creation costs are left to &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt; are charged for their second database read.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;The gas price of accessing state has not been updated for quite some time. &lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt; was included in the Berlin fork in March 2021 and raised the costs of state-accessing opcodes. Yet, since then, Ethereum’s state has grown significantly, thus deteriorating the performance of these operations. This proposal further raises state access costs to better align them with the current performance of state access operations, in relation to other operations.&lt;/p&gt;

&lt;p&gt;Additionally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt; have the same access cost as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BALANCE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODEHASH&lt;/code&gt;. However, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt; require two database reads - first to load the account object (which includes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;balance&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;codeHash&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storageRoot&lt;/code&gt;), and second to collect the required information (the code size and bytecode respectively). Therefore, the access cost of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt; should be higher when compared with the other account read operations.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;cost-components&quot;&gt;Cost components&lt;/h3&gt;

&lt;p&gt;The gas cost of a state-touching operation is the sum of up to three independent components:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Access&lt;/strong&gt; — the cost of loading an account or storage slot from the database: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_STORAGE_ACCESS&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;, renamed by this EIP from the &lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt; parameters. This EIP raises &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_STORAGE_ACCESS&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; are unchanged; the &lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt; rules that determine whether an access is cold or warm are unchanged.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Write&lt;/strong&gt; — the cost of writing an object’s leaf values when they change, whether or not the leaf already exists: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; for a storage slot and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; for an account’s leaf values (nonce, balance, code hash), both introduced by this EIP. The pre-existing schedule has no standalone constant for this component; it is fused into composites such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_STORAGE_UPDATE&lt;/code&gt; (&lt;a href=&quot;/EIPS/eip-2200&quot;&gt;EIP-2200&lt;/a&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE_RESET_GAS&lt;/code&gt;), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_VALUE&lt;/code&gt; (the Yellow Paper’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G_callvalue&lt;/code&gt;) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G_create&lt;/code&gt;). The two write surcharges follow different charging disciplines, stated once here and applying everywhere below:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; is net-metered within a transaction: it is charged by each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; that moves a slot away from its transaction-start value and credited back by each later &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; that restores that value (refund rule 3 below), so a slot that ends the transaction with a changed value pays it exactly once and a slot that ends unchanged pays only access costs, subject to the refund cap.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; is charged per operation that writes an account’s leaf values. For every operation specified in this EIP there is no per-account tracking and no refund: a value-bearing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; to the same recipient pays it on each call. (&lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt; charges it at most once per authority per transaction when processing &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; authorizations; that first-write rule is defined there and applies only to authorization processing.)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;State creation&lt;/strong&gt; — the cost of adding a new leaf to the state: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_STORAGE_SET&lt;/code&gt; for a new storage slot and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; for a new account. This EIP does not reprice these constants; they are repriced by &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt; and charged to its state-gas dimension. This EIP states where the component applies so that each operation’s complete cost is visible in one place.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The sections below specify each operation as a consumer of this model: which access cost applies, whether and when a write surcharge applies, and which state-creation charge accompanies it.&lt;/p&gt;

&lt;h3 id=&quot;parameters&quot;&gt;Parameters&lt;/h3&gt;

&lt;p&gt;Upon activation of this EIP, the following parameters of the gas model are introduced/updated:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Parameter&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Component&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Current value&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;New value&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Increase&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Operations affected&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Access&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Cold touch of an account. Renamed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS_COST&lt;/code&gt; (&lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt;)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2,600&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;3,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+15%&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*CALL&lt;/code&gt; opcodes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BALANCE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXT*&lt;/code&gt; opcodes, EOA delegation resolution, EOA delegation setting (5), contract creation txs / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; (4), and ETH transfers&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_STORAGE_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Access&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Cold touch of a storage slot. Renamed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_SLOAD_COST&lt;/code&gt; (&lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt;)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2,100&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2,100&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0%&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOAD&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Access&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Touch of an already-warm account or storage slot. Renamed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_STORAGE_READ_COST&lt;/code&gt; (&lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt;)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;100&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;100&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0%&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOAD&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*CALL&lt;/code&gt; opcodes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BALANCE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXT*&lt;/code&gt; opcodes, EOA delegation resolution, EOA delegation setting (5)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Write&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Write to an account’s leaf values (nonce, balance, code hash); charged per operation. New named parameter (previously embedded in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_VALUE&lt;/code&gt;, see footnote 1)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;6,700 (1)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;9,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+34%&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;value-transferring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*CALL&lt;/code&gt; opcodes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;, contract creation txs / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; (4), EOA delegation setting&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Write&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Write that changes a storage slot’s value; net-metered per transaction. New named parameter (previously derived, see footnote 2)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2,800 (2)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+257%&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Access + write&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Combined access-and-write cost of contract deployment: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;. New named parameter (previously derived, see footnote 3)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;7,000 (3)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+71%&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;contract creation txs / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_CLEAR_REFUND&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Refund&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Refund for clearing a storage slot. Renamed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE_CLEARS_SCHEDULE&lt;/code&gt; (&lt;a href=&quot;/EIPS/eip-3529&quot;&gt;EIP-3529&lt;/a&gt;)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;4,800&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;11,616&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+142%&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCESS_LIST_STORAGE_KEY_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Access (prepaid)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Gas charged per storage key included in a transaction’s access list. Unchanged name from &lt;a href=&quot;/EIPS/eip-2930&quot;&gt;EIP-2930&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1,900&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+5%&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOAD&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCESS_LIST_ADDRESS_COST&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Access (prepaid)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Gas charged per address included in a transaction’s access list. Unchanged name from &lt;a href=&quot;/EIPS/eip-2930&quot;&gt;EIP-2930&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2,400&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2,900&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+21%&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*CALL&lt;/code&gt; opcodes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BALANCE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXT*&lt;/code&gt; opcodes&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;(1): 6,700 = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_VALUE&lt;/code&gt; (the Yellow Paper’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G_callvalue&lt;/code&gt;, 9,000) - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_STIPEND&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G_callstipend&lt;/code&gt;, 2,300)&lt;/p&gt;

&lt;p&gt;(2): 2,800 = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_STORAGE_UPDATE&lt;/code&gt; (&lt;a href=&quot;/EIPS/eip-2200&quot;&gt;EIP-2200&lt;/a&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE_RESET_GAS&lt;/code&gt;, 5,000) - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_COLD_SLOAD&lt;/code&gt; (2,100) - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_WARM_ACCESS&lt;/code&gt; (100)&lt;/p&gt;

&lt;p&gt;(3): 7,000 = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt; (the Yellow Paper’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G_create&lt;/code&gt;, 32,000) - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G_newaccount&lt;/code&gt;, 25,000)&lt;/p&gt;

&lt;p&gt;(4): Charged only as part of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt;, not separately — these operations pay &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt; once, and never &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; on top of it. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; charge is specified in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; section below; the contract-creation transaction charge is specified in &lt;a href=&quot;/EIPS/eip-2780&quot;&gt;EIP-2780&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(5): Charged only as part of &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXECUTION_PER_AUTH_BASE_COST&lt;/code&gt;. Setting a delegation is distinct from resolving one: resolution loads the delegation target’s code at runtime and is charged the standard cold or warm access directly.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt; are new parameters with no pre-existing counterpart; their “Current value” column shows the equivalent cost extracted from the pre-existing composite constants per the footnotes above. The pre-existing schedule is not exactly separable into these components, so these equivalents are approximate: footnote 2 yields the write component of the current warm-case &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; charge exactly (2,900 = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_WARM_ACCESS&lt;/code&gt; + 2,800), while the cold-case charge of 5,000 exceeds the sum of its components by 100; footnote 3 is discussed in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; section below.&lt;/p&gt;

&lt;h3 id=&quot;sstore-pricing&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; pricing&lt;/h3&gt;

&lt;p&gt;In addition, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; cost formula is updated. As in &lt;a href=&quot;/EIPS/eip-2200&quot;&gt;EIP-2200&lt;/a&gt;, the &lt;em&gt;original value&lt;/em&gt; is the slot’s value at the start of the current transaction and the &lt;em&gt;current value&lt;/em&gt; is its value just before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; executes. The complete &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; charge is the sum of its three cost components:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Access component: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_STORAGE_ACCESS&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;, depending on whether the storage slot is cold or warm.&lt;/li&gt;
  &lt;li&gt;Write component: additionally charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; if the new value is different from the current value and the current value equals the original value (the write moves the slot away from its transaction-start value).&lt;/li&gt;
  &lt;li&gt;State-creation component: additionally charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_STORAGE_SET&lt;/code&gt; (per &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;, metered in state-gas) if the original value is zero, the current value is zero, and the new value is non-zero.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Refunds are also updated as follows. Each rule is an adjustment to the transaction’s refund counter and is evaluated on every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_CLEAR_REFUND&lt;/code&gt; is added if the original value is non-zero, the current value is non-zero and the new value is zero (a slot is cleared).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_CLEAR_REFUND&lt;/code&gt; is subtracted if the original value is non-zero, the current value is zero and the new value is non-zero (a slot that was cleared earlier in the same transaction is set to a non-zero value again, whether or not that value is its original one). This reverses the refund granted by rule 1, so that clearing and then re-setting a slot within the same transaction is never net-profitable.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; is refunded if the new value equals the original value and differs from the current value (a change made earlier in the same transaction is undone, restoring the slot’s transaction-start value).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Rules 2 and 3 mirror the refund accounting of &lt;a href=&quot;/EIPS/eip-2200&quot;&gt;EIP-2200&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-3529&quot;&gt;EIP-3529&lt;/a&gt; for slots that are modified more than once within a transaction: a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; charge or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_CLEAR_REFUND&lt;/code&gt; granted on an earlier &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; to the same slot is undone when a later &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; returns the slot to its original value. Without these reversals, a round trip such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x → 0 → x&lt;/code&gt; would yield a net refund even though the slot ends the transaction unchanged. Net over the whole transaction, a slot that ends at a changed value pays its write and state-creation components exactly once, and a slot that ends at its original value pays only its access costs — in both cases regardless of how often the slot was written, and subject to the refund cap.&lt;/p&gt;

&lt;p&gt;These refunds go to the transaction’s refund counter and are capped to 20% of the total gas used by the transaction, as per the current refund mechanism.&lt;/p&gt;

&lt;p&gt;The rules for state creation cost charges and refills are addressed in &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cases and their corresponding costs are detailed in the table below:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Original value&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Current value&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;New value&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Access status&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Description&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Execution-gas charges/refunds&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;State-gas charges/refills&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Cold&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;New slot&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_STORAGE_ACCESS&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; charged&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_STORAGE_SET&lt;/code&gt; charged&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;New slot&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; charged&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_STORAGE_SET&lt;/code&gt; charged&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;y&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Cold&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Existing slot, first change&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_STORAGE_ACCESS&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; charged&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;y&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Existing slot, first change&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; charged&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Cold&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Cleared slot, non-zero at transaction start&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_STORAGE_ACCESS&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; charged, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_CLEAR_REFUND&lt;/code&gt; refunded&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Cleared slot, non-zero at transaction start&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; charged, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_CLEAR_REFUND&lt;/code&gt; refunded&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Set slot reset to zero (zero at transaction start)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; charged, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; refunded&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_STORAGE_SET&lt;/code&gt; refilled&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;y&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Slot set earlier in the transaction written to a different non-zero value&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; charged&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;y&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Previously-modified slot reset to original value&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; charged, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; refunded&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;y&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Previously-modified slot cleared, non-zero at transaction start&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; charged, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_CLEAR_REFUND&lt;/code&gt; refunded&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Cleared slot restored to original value&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; charged, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt; refunded, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_CLEAR_REFUND&lt;/code&gt; reversed&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;y&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Cleared slot written to a new non-zero value&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; charged, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_CLEAR_REFUND&lt;/code&gt; reversed&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;y&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;z&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Warm&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Previously-modified slot written to another non-zero value&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; charged&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;no state-gas adjustments&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;account-access-pricing&quot;&gt;Account access pricing&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt; rules that determine whether an account access is cold or warm are unchanged; this EIP raises the cold access cost and states explicitly, per operation below, where the write and state-creation components apply.&lt;/p&gt;

&lt;h4 id=&quot;callcallcode&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALLCODE&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALLCODE&lt;/code&gt; operations, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_VALUE&lt;/code&gt; (the Yellow Paper’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G_callvalue&lt;/code&gt;) is redefined as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE + CALL_STIPEND&lt;/code&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_STIPEND&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G_callstipend&lt;/code&gt;, 2,300) is unchanged. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; here prices the write to the recipient’s balance leaf and, per its charging discipline, is paid on every value-transferring call. The state-creation component of a value-transferring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; to a dead account (as defined in &lt;a href=&quot;/EIPS/eip-161&quot;&gt;EIP-161&lt;/a&gt;) is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt;, which this EIP does not reprice; it is repriced and metered in state gas by &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALLCODE&lt;/code&gt; never incurs it: its recipient is the calling account itself, which already exists.&lt;/p&gt;

&lt;h4 id=&quot;createcreate2&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; operations don’t have explicit warm/cold pricing. Instead, the flat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt; (the Yellow Paper’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G_create&lt;/code&gt;, 32,000) is replaced by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt;, charged in execution gas, plus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt;, charged in state gas (per &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt;, defined as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;, is the combined access-and-write component of the deployment; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; is its state-creation component and is not repriced by this EIP.&lt;/p&gt;

&lt;p&gt;Note: this definition does not exactly match the legacy decomposition shown in footnote 3 of the Parameters table (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; = 7,000). The pre-existing accounting in the protocol is not internally consistent here, and this EIP keeps the discrepancy rather than attempting to reconcile it.&lt;/p&gt;

&lt;h4 id=&quot;selfdestruct&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;, charge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; in execution gas if the beneficiary is cold, regardless of the balance being transferred. A warm beneficiary incurs no access charge: the &lt;a href=&quot;/EIPS/eip-2929&quot;&gt;EIP-2929&lt;/a&gt; exemption from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; is preserved, including when the beneficiary is the executing account itself or a precompile. The opcode base cost and the rules for determining and updating the beneficiary’s cold or warm status are unchanged.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;, an additional charge of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; is added if a positive balance is sent to a dead account (as defined in &lt;a href=&quot;/EIPS/eip-161&quot;&gt;EIP-161&lt;/a&gt;) — the write component of creating the beneficiary’s leaf. The state-creation component in this same case is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt;, which remains in place alongside the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; charge and is metered in state-gas by &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;ext-family-update&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXT*&lt;/code&gt; family update&lt;/h4&gt;

&lt;p&gt;Besides the current access costs, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt; are charged an additional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;overview&quot;&gt;Overview&lt;/h4&gt;

&lt;p&gt;The cases for account-related operations and their corresponding cost components are summarized in the table below. The state-creation column is charged in state-gas and is not repriced by this EIP (see &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt;).&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Operation&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Access component&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Write component (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt;)&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;State-creation component&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALLCODE&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;when value is transferred (via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_VALUE&lt;/code&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_STIPEND&lt;/code&gt;)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; transfers value to a dead account; never for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALLCODE&lt;/code&gt;, whose recipient is the calling account&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DELEGATECALL&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATICCALL&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;never (no value transfer)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;—&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;folded into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;always (folded into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_ACCESS&lt;/code&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;, replacing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_CREATE&lt;/code&gt;)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt;, plus the per-byte code-deposit cost&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; if cold; zero if warm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;when a positive balance is sent to a dead account&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_NEW_ACCOUNT&lt;/code&gt; in the same case&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BALANCE&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODEHASH&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;never&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;—&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;, plus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; for the second database read&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;never&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;—&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;empirical-estimation-of-gas-costs&quot;&gt;Empirical Estimation of Gas Costs&lt;/h3&gt;

&lt;h4 id=&quot;selecting-which-operations-to-reprice&quot;&gt;Selecting which Operations to Reprice&lt;/h4&gt;

&lt;p&gt;The parameters selected for repricing in this EIP were chosen based on the estimated million gas per second (Mgas/s) performance of their respective operations. For this EIP, a performance target of &lt;strong&gt;100 million gas per second&lt;/strong&gt; is chosen. With this performance target, we will be able to increase the base throughput of the chain by a factor of 5 from our current 20 Mgas/s performance.&lt;/p&gt;

&lt;h4 id=&quot;data-collection&quot;&gt;Data Collection&lt;/h4&gt;

&lt;p&gt;The gas costs proposed in this EIP are based on the actual time each execution client takes to run a specific set of benchmarks. Similar to the methodology used in the Gas Cost Estimator project, we generate synthetic blocks that isolate and stress individual EVM operations and use them to derive the various gas parameters.&lt;/p&gt;

&lt;p&gt;Concretely, to benchmark a single operation/parameter, different blocks are created by varying the number of times the target operation is executed and by changing the parameter values to the operation. The EEST benchmark suite contains the tests used to generate these blocks.&lt;/p&gt;

&lt;p&gt;Then, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Benchmarkoor&lt;/code&gt; tool is used to collect the needed metrics. This tool returns the total execution time of the block and the number of times each operation was executed. Each test block is run multiple times on each client to account for variability in execution time.&lt;/p&gt;

&lt;p&gt;All benchmarks were run on top of a snapshot with the same size as mainnet in March 2026, so they reflect the current performance of state access operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about differences between client implementations?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ultimately, we require a single cost model that is independent of the client’s implementation. Although the decision may be different in a specific situation, the general rule is to take the worst client result that cannot be optimized. This means that the worst-performing client on a given operation and resource combination will define the cost of that operation for the entire network. This is the safer and most conservative choice.&lt;/p&gt;

&lt;h4 id=&quot;runtime-estimation&quot;&gt;Runtime Estimation&lt;/h4&gt;

&lt;p&gt;To estimate the runtime of a single operation from the total execution time of the corresponding synthetic blocks, a &lt;strong&gt;Non-Negative Least Squares Linear Regression&lt;/strong&gt; is used. This model enforces that all coefficients are non-negative, thus ensuring execution time cannot be negative. The model estimates runtime as a linear combination of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Constant term (intercept)&lt;/strong&gt;: Base overhead for executing the test, which includes setup and tear-down time&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Operation count (slope)&lt;/strong&gt;: Number of times the operation is executed in the test. This parameter is the one that allows us to estimate the per-operation runtime.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Operation-specific parameters (e.g., update)&lt;/strong&gt;: Extra per-operation runtime contributed by an additional, operation-specific binary or numeric input (e.g., whether a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; is made with value, or whether the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; writes a new value). The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt; coefficient gives the marginal runtime added per execution for storage writes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For simple operations (i.e., without additional parameters), the model estimates: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtime = intercept + slope × operation_count&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For variable operations, the model estimates: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtime = intercept + slope × operation_count + param1_coef × operation_count × param1 + param2_coef × operation_count × param2 + ...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Independent models are created for each client, operations, and configuration. Only operations and parameters with good model fits (R-squared &amp;gt; 0.5 and p-value &amp;lt; 0.05) are included in the gas cost proposal to ensure the reliability of the estimates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Glue opcode adjustment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each benchmark test includes auxiliary “glue” opcodes that scale linearly with the main opcode count. The regression slope captures the combined runtime of both the target opcode and its glue opcodes, so we subtract the estimated glue opcode runtime to isolate the true per-execution cost:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adjusted_slope = slope - sum(ratio_i * glue_runtime_i)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where, for each glue opcode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ratio_i&lt;/code&gt; is the number of executions of glue opcode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; per execution of the target opcode in the benchmark test.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glue_runtime_i&lt;/code&gt; is the estimated per-execution runtime of glue opcode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;, taken from its own regression model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only glue opcodes with a statistically significant fit (p-value &amp;lt; 0.05) are included. The adjusted slope is clipped to a minimum of zero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parameter mapping&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each gas parameter is derived from one or more benchmark models by selecting a specific regression coefficient (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slope&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt;) after applying the relevant filters (test name, cache strategy, account mode). The two coefficients correspond directly to the two cost components this EIP prices: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slope&lt;/code&gt; measures the cost of loading the object from the database (the access component), while the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt; coefficient measures the marginal cost of changing its value (the write component). The state-creation component is not estimated from runtime at all — it prices durable state growth rather than execution time — which is why it is derived separately in &lt;a href=&quot;/EIPS/eip-8037&quot;&gt;EIP-8037&lt;/a&gt; and left unchanged here.&lt;/p&gt;

&lt;p&gt;For each parameter and client, the worst-case value across all matching model configurations is used. The final proposal takes the worst case across clients.&lt;/p&gt;

&lt;p&gt;The following table lists the directly estimated parameters and their mapping to the regression models:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Test name&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Configuration&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Model&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Parameter mapping&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_account_access&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CacheStrategy = NO_CACHE&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;runtime = intercept + slope × operation_count + update × value_sent x operation_count&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slope&lt;/code&gt; → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCOUNT_ACCESS&lt;/code&gt;; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt; → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCOUNT_WRITE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_sload_bloated&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CacheStrategy = NO_CACHE&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;runtime = intercept + slope × operation_count&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slope&lt;/code&gt; → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_STORAGE_ACCESS&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_sstore_bloated&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CacheStrategy = NO_CACHE&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;runtime = intercept + slope × operation_count + update × write_new_value x operation_count&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slope&lt;/code&gt; → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_STORAGE_ACCESS&lt;/code&gt;; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt; → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STORAGE_WRITE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_sload_same_key_benchmark&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;—&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;runtime = intercept + slope × operation_count&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slope&lt;/code&gt; → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_ext_account_query_warm&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;—&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;runtime = intercept + slope × operation_count&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slope&lt;/code&gt; → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_sstore_bloated&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_sload_bloated&lt;/code&gt; targeted a bespoke contract with a storage size of 10 gigabytes, which is the size of the largest mainnet contract.&lt;/p&gt;

&lt;h4 id=&quot;conversion-to-gas-costs&quot;&gt;Conversion to gas costs&lt;/h4&gt;

&lt;p&gt;New gas costs are calculated using the same target performance of 100 Mgas/s. The formula used is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;new_gas = (anchor_rate * runtime_ms) / 1000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchor_rate&lt;/code&gt; is the target performance expressed in gas per second (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100_000_000&lt;/code&gt; for a 100 Mgas/s target).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtime_ms&lt;/code&gt; is the estimated runtime per operation, in milliseconds, taken from the regression models (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adjusted_slope&lt;/code&gt; defined above).&lt;/li&gt;
  &lt;li&gt;The factor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1000&lt;/code&gt; converts &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtime_ms&lt;/code&gt; from milliseconds to seconds, so that the product with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchor_rate&lt;/code&gt; (gas/second) yields a result in gas units.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Derived parameters&lt;/strong&gt; are computed from the directly estimated ones:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;STORAGE_CLEAR_REFUND         = (STORAGE_WRITE + COLD_STORAGE_ACCESS) * (4800/5000)
ACCESS_LIST_STORAGE_KEY_COST = COLD_STORAGE_ACCESS - WARM_ACCESS
ACCESS_LIST_ADDRESS_COST     = COLD_ACCOUNT_ACCESS - WARM_ACCESS
CREATE_ACCESS                = ACCOUNT_WRITE + COLD_ACCOUNT_ACCESS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The two access-list parameters price the same database load as their cold counterparts, so they are derived from those cold costs. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; is subtracted because a slot or account named in the access list is already warm when the transaction touches it and is therefore still charged &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; at that point: prepaying via the access list must not cost more in access gas than taking the cold access. Without the subtraction, an access-list entry that is used exactly once would cost &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COLD_ACCESS + WARM_ACCESS&lt;/code&gt; in access gas, making the list strictly more expensive than not using it. The invariant covers the access component only; charges that other EIPs levy on the access list’s bytes, such as floor costs, fall outside it.&lt;/p&gt;

&lt;h3 id=&quot;interaction-with-eip-7928&quot;&gt;Interaction with &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; introduces Block-Level Access Lists, which enable parallel disk reads, parallel transaction validation, and state updates without execution through client optimizations. Our benchmarks already consider these optimization gains by running on clients with the optimizations implemented.&lt;/p&gt;

&lt;h3 id=&quot;special-case-for-extcodesize-and-extcodecopy&quot;&gt;Special case for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Differently from other account read operations, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODESIZE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXTCODECOPY&lt;/code&gt; make two reads to the database. The first read is the same, where the object of the target account is loaded. This object includes the account’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;balance&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;codeHash&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storageRoot&lt;/code&gt;. Then, these operations do another read to collect either the code size or the bytecode of the account. This second read is to an already warmed account, and thus we propose to price it as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARM_ACCESS&lt;/code&gt; for consistency.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This is a backwards-incompatible gas repricing that requires a scheduled network upgrade.&lt;/p&gt;

&lt;p&gt;Wallet developers and node operators MUST update gas estimation handling to accommodate the new state access cost rules. Specifically:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wallets: Wallets using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth_estimateGas&lt;/code&gt; MUST be updated to ensure that they correctly account for the updated gas parameters. Failure to do so could result in underestimating gas, leading to failed transactions.&lt;/li&gt;
  &lt;li&gt;Node Software: RPC methods such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth_estimateGas&lt;/code&gt; MUST incorporate the updated formula for gas calculation with the new state access cost values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users can maintain their usual workflows without modification, as wallet and RPC updates will handle these changes.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;Changing the cost of state access operations could impact the usability of certain applications. More analysis is needed to understand the potential effects on various dApps and user behaviors.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 03 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8038</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8038</guid>
      </item>
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Exclude slashed validators from proposing</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8045 - Exclude slashed validators from proposing&lt;/strong&gt; is in Last Call status. It is authored by Francesco D&apos;Amato (@fradamt), Barnabas Busa (@barnabasbusa) and was originally created 2025-10-16. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8045-exclude-slashed-validators-from-proposing/25850&quot;&gt;https://ethereum-magicians.org/t/eip-8045-exclude-slashed-validators-from-proposing/25850&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP proposes a modification to the beacon chain proposer selection process to exclude slashed validators from being selected as proposers.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Currently, slashed validators can still be selected as proposers, though their blocks are considered invalid by the state transition function, resulting in missed slots. This is in particular problematic after a mass slashing event, at which point there can be a long period with degraded chain performance, until all slashed validators are exited. If mass slashing also comes with general network disruption, the missed slots can also significantly complicate the recovery process. This change filters out slashed validators during proposer selection, reducing disruption and increasing resilience in such scenarios.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_beacon_proposer_indices&lt;/code&gt; function in the consensus specifications is modified to exclude slashed validators from the proposer selection process, effectively going from considering all
active validators to all active and unslashed validators.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_beacon_proposer_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BeaconState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Epoch&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ValidatorIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SLOTS_PER_EPOCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Return the proposer indices for the given ``epoch``.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Modified to exclude slashed validators
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;indices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_active_validator_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slashed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DOMAIN_BEACON_PROPOSER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_proposer_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;why-exclude-slashed-validators&quot;&gt;Why exclude slashed validators?&lt;/h3&gt;

&lt;p&gt;Slashed validators are already prevented from successfully proposing blocks through the state transition validation. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_block&lt;/code&gt; function checks that the proposer is not slashed, and blocks from slashed proposers are considered invalid. Therefore, selecting slashed validators as proposers serves no purpose and only results in missed slots.&lt;/p&gt;

&lt;h3 id=&quot;design-decision-upfront-filtering&quot;&gt;Design decision: upfront filtering&lt;/h3&gt;

&lt;p&gt;The chosen approach is to simply filter out slashed validators from the candidate pool, before doing any shuffling computation. An alternative design would be to still use the whole active validator set as the candidate pool, and then only filter out slashed validators once their index has been selected by the shuffle. The exact selection is not identical, but it achieves the same goal, i.e., a balance-weighted selection from the set of active-and-unslashed validators. The complexity is low in either design.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP introduces a backwards-incompatible change to the consensus rules and MUST be activated as part of a scheduled network upgrade.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Test cases should verify that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Slashed validators are not selected as proposers&lt;/li&gt;
  &lt;li&gt;A complete &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proposer_lookahead&lt;/code&gt; is generated even in the presence of slashed validators&lt;/li&gt;
  &lt;li&gt;Slashings do not affect the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proposer_lookahead&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;Slashed validators are already prevented from successfully proposing blocks through the state transition validation, for good reason, as they are considered to be unreliable participants (malicious or faulty). However, they have historically still been eligible to be selected as proposers in order to ensure stability of the proposer selection mechanism, because excluding them would have severely impacted the stability of the proposer selection mechanism. In fact, any slashing processed on chain would have caused the sequence of future proposers to completely change, even within the lookahead window. However, with &lt;a href=&quot;/EIPS/eip-7917&quot;&gt;EIP-7917&lt;/a&gt;, the proposer selection is fixed in advance by storing in the Beacon state, so it would not be affected by slashings processed after the fact.&lt;/p&gt;

&lt;h3 id=&quot;impact-on-proposer-selection-distribution&quot;&gt;Impact on proposer selection distribution&lt;/h3&gt;

&lt;p&gt;This change does not affect the randomness or fairness of proposer selection among non-slashed validators. The selection algorithm remains the same, with the only difference being that slashed validators are excluded from the candidate pool.&lt;/p&gt;

&lt;h3 id=&quot;mass-slashing-scenarios&quot;&gt;Mass slashing scenarios&lt;/h3&gt;

&lt;p&gt;During mass slashing events, this change is purely beneficial to the resilience of the network, as well as to general quality of service. Instead of having many slashed validators selected as proposers (resulting in many missed slots), the network will continue to operate normally with only non-slashed validators being selected.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Thu, 16 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8045</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8045</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Increase exit and consolidation churn</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8061 - Increase exit and consolidation churn&lt;/strong&gt; is in Last Call status. It is authored by Francesco D&apos;Amato (@fradamt), Anders Elowsson (@anderselowsson) and was originally created 2025-10-17. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8061-increase-churn-limits/25991&quot;&gt;https://ethereum-magicians.org/t/eip-8061-increase-churn-limits/25991&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP roughly doubles the consolidation churn, as well as quadrupling the exit churn and restoring its proportionality to total stake (though maintaining the existing cap on activations). The choice of parameters balances maintaining a sufficiently long weak subjectivity period (~7 days, roughly halving the current period) with achieving two goals: allowing for faster consolidation of the validator set, in turn accelerating the timeline to faster finality, and relieving exit queue congestion, improving staking liquidity.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7514&quot;&gt;EIP-7514&lt;/a&gt; introduced an activation cap of 8 validators per epoch (now 256 ETH per epoch) to prevent overly rapid validator set growth. &lt;a href=&quot;/EIPS/eip-7251&quot;&gt;EIP-7251&lt;/a&gt; extended this cap to exits, to make room for the newly introduced consolidation operations, without increasing the weak subjectivity period. However, the fixed cap prevents the exit churn limit from being proportional to total stake, which, all else being equal, leads to longer queues as stake grows. Moreover, the 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CHURN_LIMIT_QUOTIENT&lt;/code&gt; is set quite conservatively in the first place, requiring more than 3 months for 1/3 of the validator set to exit, a time which is now be more than doubled due to the cap. Recent episodes have stressed for more headroom to improve liquidity and staking user experience, as the exit queue has stretched beyond forty days as a consequence of the mass exit of Kiln validators. Long queues degrade user experience, and slow operator response to market or operational events. They also reduce the network’s ability to reconfigure stake more quickly after adverse events, for example to regain finality by having a large amount of stake exit (a double-edged sword, as preventing double finality is the reason these queues exist in the first place, as discussed in the security section). Finally, centralized forms of staking are those that (in relative terms) benefit the most from a lack of liquidity today, as they have the ability to issue a liquid staking token, maintain liquidity reserves or more generally build products that get around the limitations of the protocol.&lt;/p&gt;

&lt;p&gt;The conservative setting of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CHURN_LIMIT_QUOTIENT&lt;/code&gt; affects consolidations as well. Increasing the consolidation churn limit can shorten the path to a smaller validator set and, in turn, the path to a protocol with much faster finality. Under today’s parameters, even the best-case timelines are long: using only activations and exits, fully saturated around the clock, shrinking the roughly 32M ETH of 0x01 stake would take on the order of ~1.5 years; a fully saturated consolidation queue would still take ~1.3 years. Moreover, deposit capacity is also needed for new stake and is thus far from guaranteed to be available for consolidations, as evidenced by the recent inflow of &amp;gt; 1M ETH, fully occupying the queue for ~20 days.&lt;/p&gt;

&lt;p&gt;The EIP proposes to address these issues by:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;removing the cap on exits, restoring the proportionality of exit churn limit to total stake&lt;/li&gt;
  &lt;li&gt;increasing the churn limit on exits&lt;/li&gt;
  &lt;li&gt;introducing a separate consolidation churn limit, since there is no more “excess churn” from having an exit cap, and increase it compared to the current (implicitly defined) one. This also lets us more independently adjust it in the future, for example to increase it if we want to allow for faster consolidation of the validator set or decrease it when this process has already run its course.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The EIP does &lt;em&gt;not&lt;/em&gt; propose to lift the cap on the deposit churn, as part of the motivation for introducing it in &lt;a href=&quot;/EIPS/eip-7514&quot;&gt;EIP-7514&lt;/a&gt; still holds today: though &lt;em&gt;active validator set&lt;/em&gt; growth is mostly solved by &lt;a href=&quot;/EIPS/eip-7251&quot;&gt;EIP-7251&lt;/a&gt;, the &lt;em&gt;validator array in the BeaconState&lt;/em&gt; (including inactive validators) is very large and still growing, and too rapid &lt;em&gt;stake&lt;/em&gt; growth continues to be a concern as well.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CHURN_LIMIT_QUOTIENT&lt;/code&gt; is halved, from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2**16&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2**15&lt;/code&gt;, and fully dedicated to activations and exits. However, the cap on activations introduced in &lt;a href=&quot;/EIPS/eip-7514&quot;&gt;EIP-7514&lt;/a&gt; is maintained via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT&lt;/code&gt;, while exits are freed from this cap. Consolidations now have their own dedicated churn, determined by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONSOLIDATION_CHURN_LIMIT_QUOTIENT&lt;/code&gt;. This is set here to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2**16&lt;/code&gt;, so that consolidations are allocated half as much churn as activations and exits combined, and a third of the total churn. Finally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compute_weak_subjectivity_period&lt;/code&gt; is adjusted to account for the asymmetry between exit and activation churn: a unit of exit churn has twice the weak subjectivity effect ($\frac{4}{3}$) of a unit of activation churn $\frac{2}{3}$, and a unit of consolidation churn has an effect equivalent to the sum of the other two ($2$).&lt;/p&gt;

&lt;h3 id=&quot;configuration&quot;&gt;Configuration&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT&lt;/code&gt; replaces the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT&lt;/code&gt;, also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;256&lt;/code&gt;, as the cap now only applies to activations. We introduce the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONSOLIDATION_CHURN_LIMIT_QUOTIENT&lt;/code&gt; and update the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CHURN_LIMIT_QUOTIENT&lt;/code&gt;.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CHURN_LIMIT_QUOTIENT_GLOAS&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(2**15)&lt;/code&gt; (= 32,768)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONSOLIDATION_CHURN_LIMIT_QUOTIENT&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(2**16)&lt;/code&gt; (= 65,536)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(2**8)&lt;/code&gt;  (=256)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;churn-computations&quot;&gt;Churn computations&lt;/h3&gt;

&lt;p&gt;Due to the intended asymmetry in activation and exit churn, we replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_activation_exit_churn_limit&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_activation_churn_limit&lt;/code&gt;, capped at  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_exit_churn_limit&lt;/code&gt;, uncapped. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_consolidation_churn_limit&lt;/code&gt; uses the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONSOLIDATION_CHURN_LIMIT_QUOTIENT&lt;/code&gt;, without either a minimum or a maximum value.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_activation_churn_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BeaconState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Per-epoch churn limit for activations, rounded to EFFECTIVE_BALANCE_INCREMENT.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;get_total_active_balance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHURN_LIMIT_QUOTIENT_GLOAS&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EFFECTIVE_BALANCE_INCREMENT&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_exit_churn_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BeaconState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Per-epoch churn limit for activations, rounded to EFFECTIVE_BALANCE_INCREMENT.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;get_total_active_balance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHURN_LIMIT_QUOTIENT_GLOAS&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EFFECTIVE_BALANCE_INCREMENT&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_consolidation_churn_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BeaconState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Per-epoch churn limit for consolidations (EIP-7521), rounded to EFFECTIVE_BALANCE_INCREMENT.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_total_active_balance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CONSOLIDATION_CHURN_LIMIT_QUOTIENT&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EFFECTIVE_BALANCE_INCREMENT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compute_weak_subjectivity_period&lt;/code&gt; we only replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delta = get_balance_churn_limit(state)&lt;/code&gt; with an explicit calculation taking into account the different weak subjectivity effect of each type of operation.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;compute_weak_subjectivity_period&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BeaconState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Returns the weak subjectivity period for the current ``state``.
    This computation takes into account the effect of validator set churn, 
    bounded by the three churn_limit functions used below.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_total_active_balance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;delta&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_exit_churn_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# effect of exit churn
&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_activation_churn_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# effect of activation churn
&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_consolidation_churn_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# effect of consolidation churn
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;epochs_for_validator_set_churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SAFETY_DECAY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delta&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MIN_VALIDATOR_WITHDRAWABILITY_DELAY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;epochs_for_validator_set_churn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;deposit-processing&quot;&gt;Deposit processing&lt;/h3&gt;

&lt;p&gt;The only modification is replacing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_activation_exit_churn_limit&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_activation_churn_limit&lt;/code&gt;, maintaing the current cap on deposit churn respects, while removing the cap from exits. This reverts to the pre-Electra status quo, when activations were capped but exits were not.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process_pending_deposits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BeaconState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;next_epoch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_current_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [Modified in Gloas:EIP-8061]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;available_for_processing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deposit_balance_to_consume&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_activation_churn_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;processed_amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;next_deposit_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;deposits_to_postpone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;is_churn_limit_reached&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;finalized_slot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_start_slot_at_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;finalized_checkpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pending_deposits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Do not process deposit requests if Eth1 bridge deposits are not yet applied.
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Is deposit request
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GENESIS_SLOT&lt;/span&gt;
            &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# There are pending Eth1 bridge deposits
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eth1_deposit_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deposit_requests_start_index&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Check if deposit has been finalized, otherwise, stop processing.
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finalized_slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Check if number of processed deposits has not reached the limit, otherwise, stop processing.
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_deposit_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_PENDING_DEPOSITS_PER_EPOCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Read validator state
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;is_validator_exited&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;is_validator_withdrawn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;validator_pubkeys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pubkey&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pubkey&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validator_pubkeys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;validator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ValidatorIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validator_pubkeys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pubkey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;is_validator_exited&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exit_epoch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FAR_FUTURE_EPOCH&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;is_validator_withdrawn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;withdrawable_epoch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_epoch&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_validator_withdrawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Deposited balance will never become active. Increase balance but do not consume churn
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;apply_pending_deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_validator_exited&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Validator is exiting, postpone the deposit until after withdrawable epoch
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;deposits_to_postpone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Check if deposit fits in the churn, otherwise, do no more deposit processing in this epoch.
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;is_churn_limit_reached&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;processed_amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;available_for_processing&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_churn_limit_reached&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Consume churn and apply deposit.
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;processed_amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;apply_pending_deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Regardless of how the deposit was handled, we move on in the queue.
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;next_deposit_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pending_deposits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pending_deposits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next_deposit_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deposits_to_postpone&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Accumulate churn only if the churn limit has been hit.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_churn_limit_reached&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deposit_balance_to_consume&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;available_for_processing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;processed_amount&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deposit_balance_to_consume&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;exit-processing&quot;&gt;Exit processing&lt;/h3&gt;

&lt;p&gt;We replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_activation_exit_churn_limit&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_exit_churn_limit&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;compute_exit_epoch_and_update_churn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BeaconState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_balance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gwei&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;earliest_exit_epoch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;earliest_exit_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;compute_activation_exit_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_current_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# [Modified in Gloas:EIP-8061]
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;per_epoch_churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_exit_churn_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# New epoch for exits.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;earliest_exit_epoch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;earliest_exit_epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;exit_balance_to_consume&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;per_epoch_churn&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;exit_balance_to_consume&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exit_balance_to_consume&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Exit doesn&apos;t fit in the current earliest epoch.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_balance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_balance_to_consume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;balance_to_process&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_balance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_balance_to_consume&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;additional_epochs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;balance_to_process&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;per_epoch_churn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;earliest_exit_epoch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;additional_epochs&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;exit_balance_to_consume&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;additional_epochs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;per_epoch_churn&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Consume the balance and update state variables.
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exit_balance_to_consume&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_balance_to_consume&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_balance&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;earliest_exit_epoch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;earliest_exit_epoch&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;earliest_exit_epoch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Independent parameters:&lt;/strong&gt; a separate churn consolidation is easy to independently tune, in particular adjusted upward if we want to speed up the consolidation process further, and later downward, when the primary wave of validator set consolidation has already happened and the consolidation operation becomes less crucial.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Scaling with stake&lt;/strong&gt;: the exit churn regains proportionality to the total stake, and the consolidation churn maintains it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Preserving the activation cap&lt;/strong&gt;: the activation churn limit maintains the cap from &lt;a href=&quot;/EIPS/eip-7514&quot;&gt;EIP-7514&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Balancing security and functionality&lt;/strong&gt;: the exit churn limit is increased by ~4x compared to the current cap, and exactly 2x compared to previous uncapped version, while the consolidation churn limit is increased by ~2x. Activations remain capped at the existing limit. As we see later in more detail, accounting for the asymmetric impact of exits and activations on safety degradation, this results in a decrease of the weak subjectivity period from ~15.7 days to ~7 days (see detailed calculations below), or ~6 days if we were to later remove the activation cap, in either case still on the order of a week. Moreover, were consolidations to be removed later, the weak subjectivity period would go up to ~11 days, or ~8.4 days without the activation cap.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP introduces a backwards-incompatible change to the consensus rules and MUST be activated as part of a scheduled network upgrade.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;weak-subjectivity-period&quot;&gt;Weak subjectivity period&lt;/h3&gt;

&lt;p&gt;Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MIN_VALIDATOR_WITHDRAWABILITY_DELAY = 256&lt;/code&gt; epochs, and let $S$ denote the total stake, $E$ the exit churn per epoch, $A$ the activation churn per epoch, and $C$ the consolidation churn per epoch. Each unit of exit churn contributes to a safety degradation (measured in ETH, as the churn) of $\frac{4}{3}$, whereas the safety degradation from activations is only $\frac{2}{3}$ per unit. Finally, it is $2$ per unit for consolidations, as a consolidation is the equivalent of an exit and an activation.&lt;/p&gt;

&lt;p&gt;The formula to compute the weak subjectivity period (in epochs) for a 10% safety decay target (exactly corresponding to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compute_weak_subjectivity_period&lt;/code&gt;) then is:&lt;/p&gt;

&lt;p&gt;$\text{WS}_{\text{epochs}} = 256 +
\frac{0.1 \cdot S}{\frac{4}{3} \cdot E + \frac{2}{3} \cdot A + 2 \cdot C}$&lt;/p&gt;

&lt;p&gt;The churn limits of the current protocol, assuming a total stake $S = 36M$ ETH (approximately the stake at the time of writing) are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$A = E = \min(256, S/2^{16}) = 256$ ETH (capped)&lt;/li&gt;
  &lt;li&gt;$C = S/2^{16} - A \approx 293$ ETH&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The weak subjectivity period is then:&lt;/p&gt;

&lt;p&gt;$\text{WS}_{\text{epochs}} \approx 3533$&lt;/p&gt;

&lt;p&gt;$\Rightarrow\ \textbf{WS} \approx \mathbf{15.7\ \text{days}}$&lt;/p&gt;

&lt;p&gt;In days, it is $\text{WS}_{\text{epochs}} / 225$.&lt;/p&gt;

&lt;p&gt;Under this EIP, and assuming a total stake $S = 36M$ ETH:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$E = S/2^{15} \approx 1098$ ETH&lt;/li&gt;
  &lt;li&gt;$A = \min(256, S/2^{15}) = 256$ ETH (capped)&lt;/li&gt;
  &lt;li&gt;$C = S/2^{16} \approx 549$ ETH&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The weak subjectivity period is then:&lt;/p&gt;

&lt;p&gt;$\text{WS}_{\text{epochs}} \approx 1573$&lt;/p&gt;

&lt;p&gt;$\Rightarrow\ \textbf{WS} \approx \mathbf{7.0\ \text{days}}$&lt;/p&gt;

&lt;p&gt;Other possible future scenarios are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Activation cap removed: $\textbf{WS} \approx \mathbf{6.0\ \text{days}}$ ($\text{WS}_{\text{epochs}} \approx 1348$)&lt;/li&gt;
  &lt;li&gt;Consolidations disabled: $\textbf{WS} \approx \mathbf{10.9\ \text{days}}$ ($\text{WS}_{\text{epochs}} \approx 2457$)&lt;/li&gt;
  &lt;li&gt;Consolidations disabled and activation cap removed: $\textbf{WS} \approx \mathbf{8.4\ \text{days}}$ ($\text{WS}_{\text{epochs}} \approx 1894$)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that removing the activation cap only reduces the weak subjectivity period by one day, and leaves it on the order of a week. The current parameters might then also be considered acceptable in a future where it is decided to remove the activation cap.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 17 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8061</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8061</guid>
      </item>
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Upgrade Mascots</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8066 - Upgrade Mascots&lt;/strong&gt; is in Last Call status. It is authored by Jordan Holberg (@eviljordan), Andrew B Coathup (@abcoathup) and was originally created 2025-10-29. It is in the  category of type Informational. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8066-upgrade-mascots/26009&quot;&gt;https://ethereum-magicians.org/t/eip-8066-upgrade-mascots/26009&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP establishes a mascot for each Ethereum network upgrade. Mascots serve to humanize and celebrate upgrades, fostering community engagement while adhering to principles of cuteness, relevance, and inclusivity. The mascot is selected through community-driven processes, with safeguards for appropriateness, by a designated facilitator (the “Mascot Wrestler”).&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Ethereum network upgrades often introduce complex technical changes that can feel abstract to the broader community. Mascots provide a fun, memorable, and relatable symbol for each upgrade, drawing inspiration from its headliners, the namesakes of its layer names, or its client interop events. By mandating emoji-representable mascots that are cute and non-offensive, this process:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Enhances community participation and excitement around network upgrades.&lt;/li&gt;
  &lt;li&gt;Creates opportunities for creative expression in upgrade event branding (e.g., watch parties, attendance NFTs).&lt;/li&gt;
  &lt;li&gt;Builds a consistent, whimsical tradition that differentiates Ethereum’s upgrade narrative from other ecosystems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.&lt;/p&gt;

&lt;h3 id=&quot;1-mascot-requirements&quot;&gt;1. Mascot Requirements&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Relevance&lt;/strong&gt;: The mascot &lt;strong&gt;MUST&lt;/strong&gt; relate thematically to one or more of the network upgrade’s headliners, the namesakes of the network upgrade’s layer names (e.g., the execution layer city or the consensus layer star), or the client interop events for the network upgrade.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Representation&lt;/strong&gt;: The mascot &lt;strong&gt;MUST&lt;/strong&gt; be expressible using one or more standard Unicode emojis (e.g., 🐼 for the Merge).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Form&lt;/strong&gt;: The mascot &lt;strong&gt;SHOULD&lt;/strong&gt; depict an animal (real, mythical, or stylized, but always animal-adjacent).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tone&lt;/strong&gt;: The mascot &lt;strong&gt;MUST NOT&lt;/strong&gt; be offensive (no depictions of violence, discrimination, or controversy) and &lt;strong&gt;SHOULD&lt;/strong&gt; be inherently cute (e.g., avoiding aggressive or fearsome traits unless softened for adorability).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-roles-and-responsibilities&quot;&gt;2. Roles and Responsibilities&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Mascot Wrestler&lt;/strong&gt;: A self-selected community facilitator responsible for proposing, selecting, and adopting the mascot for a network upgrade. The role &lt;strong&gt;MAY&lt;/strong&gt; rotate voluntarily per upgrade cycle to encourage diverse participation.
    &lt;ul&gt;
      &lt;li&gt;Duties include:
        &lt;ul&gt;
          &lt;li&gt;Soliciting and curating mascot candidates.&lt;/li&gt;
          &lt;li&gt;Facilitating selection processes.&lt;/li&gt;
          &lt;li&gt;Announcing the final mascot (e.g., Ethereum Magicians, All Core Devs).&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Veto Powers&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;The Mascot Wrestler &lt;strong&gt;MAY&lt;/strong&gt; veto any candidate mascot not meeting the mascot requirements above.&lt;/li&gt;
      &lt;li&gt;A rough consensus of client teams &lt;strong&gt;MAY&lt;/strong&gt; veto the selected mascot, triggering fallback to the next-highest-ranked candidate mascot.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-selection-process&quot;&gt;3. Selection Process&lt;/h3&gt;

&lt;p&gt;The Mascot Wrestler &lt;strong&gt;SHALL&lt;/strong&gt; conduct selection using one or more community-appropriate mechanisms.&lt;/p&gt;

&lt;p&gt;The process &lt;strong&gt;MUST&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Run for a minimum of 7 days.&lt;/li&gt;
  &lt;li&gt;Present at least 2 candidates.&lt;/li&gt;
  &lt;li&gt;Rank finalists by popularity.&lt;/li&gt;
  &lt;li&gt;Document results publicly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If no consensus is reached, the Mascot Wrestler selects the top candidate by default, subject to veto.&lt;/p&gt;

&lt;h3 id=&quot;4-usage-guidelines&quot;&gt;4. Usage Guidelines&lt;/h3&gt;

&lt;p&gt;All uses &lt;strong&gt;MUST&lt;/strong&gt; respect the network upgrade mascot’s cute, non-offensive nature and credit original concept creators where applicable.&lt;/p&gt;

&lt;p&gt;Mascots exist to celebrate network upgrades and &lt;strong&gt;SHOULD NOT&lt;/strong&gt; be used to promote speculative tokens (e.g., meme coins).&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;This specification balances creativity with guardrails to prevent mascot drift (e.g., unrelated or edgy choices). Emoji-based representation ensures accessibility across digital platforms, while the animal/cute mandate aligns with Ethereum’s community ethos of approachability. The self-selected Mascot Wrestler role decentralizes coordination, leveraging vetoes for accountability. Selection flexibility accommodates Ethereum’s decentralized governance evolution.&lt;/p&gt;

&lt;p&gt;Alternatives considered:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fully onchain mandates: Too rigid for creative processes.&lt;/li&gt;
  &lt;li&gt;No formal process: Risks ad-hoc or absent mascots.&lt;/li&gt;
  &lt;li&gt;Non-animal options: Animals evoke universality and whimsy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP does not directly change the Ethereum protocol. It formalizes part of the current network upgrade process.  Past upgrades (e.g., Shapella’s owl 🦉) are retroactively honored if they fit the criteria; future upgrades &lt;strong&gt;MUST&lt;/strong&gt; comply starting with the next hard fork post-adoption.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;None&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Wed, 29 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8066</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8066</guid>
      </item>
      
    
      
    
      
      
      <item>
        <title>eth/72 - Sparse Blobpool</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8070 - eth/72 - Sparse Blobpool&lt;/strong&gt; is in Last Call status. It is authored by Raúl Kripalani (@raulk), Bosul Mun (@healthykim), Francesco D&apos;Amato (@fradamt), Csaba Kiraly (@cskiraly), Felix Lange (@fjl), Marios Ioannou (@mariosioannou-create), Alex Stokes (@ralexstokes), Kamil Salakhiev (@kamilsa) and was originally created 2025-10-29. It is in the Networking category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8070-sparse-blobpool/26023&quot;&gt;https://ethereum-magicians.org/t/eip-8070-sparse-blobpool/26023&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This proposal introduces the sparse blobpool, a construction that brings cell-level, custody-aligned sampling in the Execution Layer (EL). For every new type 3 (blob-carrying) transaction, an EL node fetches full blob payloads only with probability p = 0.15, and otherwise it merely samples the blobs, using the same custody assignment as its Consensus Layer (CL) counterpart. For validators, this means downloading as little as 1/8 of the data (8 out of 64 cells), so that the average bandwidth consumption compared to the (current) full blobpool is 0.15 + 0.85/8 ~ 0.25, a ~4x reduction. The choice of p = 0.15 balances reducing bandwidth consumption with guaranteeing the full propagation of txs, by ensuring that for each blob tx there exists a large connected backbone of nodes that have the full blob payload. At an individual node level, p = 0.15 translates to 98.6% probability of least 3/50 neighbours holding the full blob payload, only 0.03% chance of total unavailability. The sampling performed with probability 1 - p = 0.85 enables streamlined data availability checks during block validation, as well as enhancing the availability of the data.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;As Blob Parameter Only (BPO) forks progressively increase throughput, the full-replication nature of today’s EL blobpool will begin dominating bandwidth utilization, causing us to hit &lt;a href=&quot;/EIPS/eip-7870&quot;&gt;EIP-7870&lt;/a&gt; limits. Furthermore, this traffic will compete, and potentially starve, block and attestation propagation, risking instability and liveness issues. This behavior has already been observed in Fusaka devnets, where the average bandwidth consumption &lt;em&gt;of a full node&lt;/em&gt; is dominated by the EL blobpool, since column propagation on the CL benefits from sampling.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/eip-8070/bandwidth-breakdown-fusaka-devnets.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 1.&lt;/strong&gt; &lt;em&gt;Breakdown of the average bandwidth consumption (download) of full nodes in Fusaka Devnet 5, for blob count target/max of 22/33 (left) and 48/72 (right). The average bandwidth consumption of the EL is ~4-5x that of the CL.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;While the average bandwidth consumption does not reflect that the load on the EL is spread out over time rather than concentrated in a small time window as it is in the CL, the gap between the EL and CL is quite large (~4-5x), and future upgrades will enable the CL to better spread out data propagation in the slot, leaving the EL blobpool as even more of a bottleneck.&lt;/p&gt;

&lt;p&gt;The sparse blobpool mechanism brings sampling to the EL as well, with an anticipated ~4x reduction in average bandwidth consumption for a given blobpool load. In doing so, it preserves the unstructured, stochastic nature of the current blobpool rather than introducing complex sharding architectures, prioritizing simplicity and resilience. Moreover, it preserves the CL’s ability to satisfy its own sampling needs with the pre-propagated data in the EL blobpool (through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getBlobs&lt;/code&gt; Engine API). This is achieved by aligning the EL and CL sampling, in particular by having the EL fetch the cells corresponding to the CL custody set. This preserves a key feature of the blobpool, as it stretches the time window for blob data propagation, offloading this work from the critical path of block validation and leading to smoother and less bursty bandwidth utilization patterns over time.&lt;/p&gt;

&lt;p&gt;While the scalability gain may be more modest than with other solutions, we believe this design balances between simplicity, security, and scalability, in order to unlock the next tier of blob throughput without requiring user-facing changes, or deeper architectural redesigns.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;execution-clients--devp2p-changes&quot;&gt;Execution clients :: devp2p changes&lt;/h3&gt;

&lt;p&gt;We introduce a new devp2p protocol version, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/72&lt;/code&gt; extending the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/71&lt;/code&gt; protocol.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewPooledTransactionHashes&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x08&lt;/code&gt;) message.&lt;/strong&gt;
Add a new field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cell_mask&lt;/code&gt; of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B_16&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint128&lt;/code&gt;). This field MUST be interpreted as a bitarray of length &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CELLS_PER_EXT_BLOB&lt;/code&gt;, carrying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; in the indices of columns the announcer has available for &lt;strong&gt;all type 3 txs announced within the message&lt;/strong&gt;. This field MUST be set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt; when no transactions of such type are announced. (TODO: this approach is not expressive enough if the node wants to offer randomly sampled columns, nor if it wants to announce transactions with full and partial availability in a single message).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;old schema (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/71&lt;/code&gt;): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[types: B, [size_0: P, size_1: P, ...], [hash_0: B_32, hash_1: B_32, ...]]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;new schema (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/72&lt;/code&gt;): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[types: B, [size_0: P, size_1: P, ...], [hash_0: B_32, hash_1: B_32, ...], cell_mask: B_16]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Modify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetPooledTransactions&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x09&lt;/code&gt;) / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PooledTransactions&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0a&lt;/code&gt;) behaviour.&lt;/strong&gt;
Responses MUST elide blob payloads for type 3 transactions requested via this RPC by encoding the transaction’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blobs&lt;/code&gt; field as the RLP empty list (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xc0&lt;/code&gt;, the encoding of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt;). The field MUST NOT be encoded as the RLP empty byte string (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x80&lt;/code&gt;). Cell proofs and commitments are unaffected and continue to be sent.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;old schema (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/71&lt;/code&gt;): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[request_id: P, [tx_0, tx_1, ...]]&lt;/code&gt;, where type 3 transactions are encoded as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x03 || rlp([tx_payload_body, wrapper_version, blobs, commitments, cell_proofs])&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;new schema (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/72&lt;/code&gt;): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[request_id: P, [tx_0, tx_1, ...]]&lt;/code&gt;, where type 3 transactions are encoded as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x03 || rlp([tx_payload_body, wrapper_version, [], commitments, cell_proofs])&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;New message type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetCells&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x14&lt;/code&gt;).&lt;/strong&gt; Used to request cells for type 3 transactions. It specifies the transaction hashes being requested, along with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cell_mask&lt;/code&gt; specifying which cell indices are needed, with syntax identical as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cell_mask&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewPooledTransactionHashes&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/72&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[[hash_0: B_32, hash_1: B_32, ...], cell_mask: B_16]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;New message type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cells&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x15&lt;/code&gt;).&lt;/strong&gt; Used to respond to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetCells&lt;/code&gt; requests.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/72&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[[hash_0: B_32, hash_1: B_32, ...], cells: [[cell_0_0: B_2048, cell_0_1: B_2048, ...], [cell_1_0: B_2048, cell_1_1: B_2048, ...]], cell_mask: B_16]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;execution-clients--blobpool-behavior&quot;&gt;Execution clients :: Blobpool behavior&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;New transaction hash.&lt;/strong&gt;
Upon receiving a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewPooledTransactionHashes&lt;/code&gt; announcement containing a previously unknown type 3 transaction hash, the node makes a probabilistic decision about fetching the blob payload: it decides to fetch the full blob payload with probability p = 0.15 (provider role), or simply sample otherwise (sampler role). This decision MAY be remembered for some period chosen by the implementer, in which case stateless heuristics are RECOMMENDED (e.g. calculating a hash by appending some time-bound value mixed in with stable transaction properties, and applying p to it).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provider role.&lt;/strong&gt;
If the node is a provider, and the announcing peer signaled full availability, the node MUST request the signed transaction and full blob data from that peer via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetPooledTransactions&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetCells&lt;/code&gt; with an all-ones &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cell_mask&lt;/code&gt; bitmap. Upon successful retrieval and validation (as per &lt;a href=&quot;/EIPS/eip-7594&quot;&gt;EIP-7594&lt;/a&gt;), the node MUST in turn announce the transaction hash to its peers via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewPooledTransactionHashes&lt;/code&gt;, also with an all-ones &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cell_mask&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sampler role.&lt;/strong&gt;
If the node is a sampler, the node MUST only request the transaction payload via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetPooledTransactions&lt;/code&gt;. It SHOULD await to observe at least 2 distinct provider announcements, and to successfully receive and validate the signed transaction, before acting further. It then MUST request custody-aligned cells from peers that announced overlapping availability, including providers. When fetching from a provider, the node MUST request &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_extra&lt;/code&gt; random columns in addition to its custody set (see “Sampling noise” in Rationale). The responder MAY truncate its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cells&lt;/code&gt; response depending on its current capacity, returning fewer cells than requested.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ensuring fairness.&lt;/strong&gt;
Nodes MAY keep a record of the frequency of full payload fetches made by each peer, relative to their sampling requests. Nodes MAY elect to disconnect peers who exceed some locally-determined fairness heuristic. Such heuristics are not object of standardization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supernode behaviour.&lt;/strong&gt;
Supernodes (nodes intending to fetch every blob payload in full) MUST load balance requests across samplers and providers. Furthermore, supernodes SHOULD prioritize reconstructing blobs and proofs from 64 columns. Supernodes SHOULD maintain a larger peerset in order to satisfy their increased blob fetching needs without over-stressing a small set of neighbours and violating fairness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sampler eviction&lt;/strong&gt;
A sampler MAY drop a transaction if it has not observed sufficient network saturation (i.e., announcements from other peers for the same blob) within a defined period.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continued sampling&lt;/strong&gt;
Tenured transactions MAY be subject to resampling in order to test for liveness and confirm confidence of continued network-wide availability.&lt;/p&gt;

&lt;h3 id=&quot;execution-clients--local-block-builders&quot;&gt;Execution clients :: Local block builders&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Eager mode for block builders.&lt;/strong&gt;
By default block builder &lt;strong&gt;SHOULD&lt;/strong&gt; permanently act in eager mode: it acts as a provider (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p = 1.0&lt;/code&gt;) for every type 3 transaction it intends to include, fetching the full blob payload. This guarantees that the builder holds complete blob data for all transactions in the payload.&lt;/p&gt;

&lt;p&gt;A builder &lt;strong&gt;MAY&lt;/strong&gt; choose to act as a provider with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p = 0.15&lt;/code&gt; probability, and switch to eager mode 2-3 slots prior to block building. But this is not recommended as this creates a clear pattern for the builder’s networking behavior and compromises its privacy, increasing the risk of DoS attacks against it.&lt;/p&gt;

&lt;h3 id=&quot;engine-api-extensions&quot;&gt;Engine API extensions&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_forkchoiceUpdatedV4&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This EIP extends &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_forkchoiceUpdatedV4&lt;/code&gt; as defined in the Amsterdam Engine API specification by adding an optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;custodyColumns&lt;/code&gt; parameter, allowing the CL to inform the EL of its current blob column custody set.&lt;/p&gt;

&lt;p&gt;Request:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;method: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_forkchoiceUpdatedV4&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;params:
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forkchoiceState&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ForkchoiceStateV1&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payloadAttributes&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object|null&lt;/code&gt; - Instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PayloadAttributesV4&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;custodyColumns&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DATA|null&lt;/code&gt; - 16-byte value interpreted as a bitarray of length &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CELLS_PER_EXT_BLOB&lt;/code&gt;, where a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; at position &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; indicates the CL node has custody of column &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; if the CL is unable to provide an update.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;timeout: 8s&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Response:&lt;/p&gt;

&lt;p&gt;Refer to the response for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_forkchoiceUpdatedV3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Specification:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;CL MUST include a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;custodyColumns&lt;/code&gt; value after startup or when its columns custody set changes. It MUST also resend it after any Engine API interruption or reconnection.&lt;/li&gt;
  &lt;li&gt;EL MUST return an Ok response if the request is well-formed. All subsequent sampling requests MUST adopt the new custody set. Queued sampling requests MAY be patched to reflect the new custody set.&lt;/li&gt;
  &lt;li&gt;For type 3 transactions pending in the blobpool:
    &lt;ol&gt;
      &lt;li&gt;If the custody set has expanded relative to the previously known set, the Execution client MUST issue new sampling requests for the delta columns. It SHOULD broadcast updated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewPooledTransactionHashes&lt;/code&gt; announcements reflecting the expanded available set when act as a sampler.&lt;/li&gt;
      &lt;li&gt;If the custody set has contracted, the Execution client MAY prune dropped cells from local storage, but only AFTER broadcasting an updated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewPooledTransactionHashes&lt;/code&gt; announcement with the reduced available set, to avoid peers perceiving availability fault.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;The Execution client MUST treat a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;custodyColumns&lt;/code&gt; value identical to the current custody set or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; value as a no-op with respect to blobpool state, while still processing the rest of the forkchoice update normally.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_getBlobsV4&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Called by the Consensus layer client to retrieve blob cells from the Execution layer blobpool.&lt;/p&gt;

&lt;p&gt;Request:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;method: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engine_getBlobsV4&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;params:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;versioned_blob_hashes&lt;/code&gt;: []bytes32, an array of blob versioned hashes.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indices_bitarray&lt;/code&gt;: uint128, a bitarray denoting the indices of the cells to retrieve.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;timeout: 500ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Response:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;result: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]BlobCellsAndProofsV1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;error: code and message set in case an error occurs during processing of the request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data structure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlobCellsAndProofsV1&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blob_cells&lt;/code&gt;: a sequence of byte arrays &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]bytes&lt;/code&gt; representing the partial matrix of the requested blobs, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt; entries for missing cells.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proofs&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array of DATA&lt;/code&gt; - Array of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KZGProof&lt;/code&gt; as defined in &lt;a href=&quot;/EIPS/eip-4844&quot;&gt;EIP-4844&lt;/a&gt;, 48 bytes each (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DATA&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;parameters&quot;&gt;Parameters&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Fetching probability&lt;/strong&gt;: p = 0.15&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Mesh degree&lt;/strong&gt;: D = 50 (default peerset size)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Sampling requirement&lt;/strong&gt;: Minimum &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SAMPLES_PER_SLOT = 8&lt;/code&gt; columns per node as per PeerDAS specification&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Reconstruction threshold&lt;/strong&gt;: 64 cells required for Reed-Solomon decoding&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Minimum providers to sample&lt;/strong&gt;: minimum 2 providers should be observed before sampling&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Extra random columns per request&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_extra = 1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;parameter-selection&quot;&gt;Parameter selection&lt;/h3&gt;

&lt;p&gt;The choice of p = 0.15 balances bandwidth reduction with availability guarantees. Mathematical analysis for a mesh degree D = 50 shows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Primary reliability&lt;/strong&gt;: Probability of having at least 3 peers with complete blob payload is 98.6%&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Secondary reliability&lt;/strong&gt;: Via reconstruction from partial availability, recovery probability exceeds 80% when 6+ provider peers exist.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Total unavailability&lt;/strong&gt;: Only 0.03% chance with these parameters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;reliability-framework&quot;&gt;Reliability framework&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Primary reliability.&lt;/strong&gt; Let $X$ be the number of direct peers with the full payload. With $X∼Binomial(D,p)$, the probability that at least $k$ honest peers hold the full blob payload for a type 3 tx is:&lt;/p&gt;

\[P(X \geq k) = 1 - \sum_{i=0}^{k-1} \binom{D}{i} p^i (1-p)^{D-i}\]

&lt;p&gt;Evaluating for sensible values of $p$ and $k$ yields, where $D=50$ (Geth’s default mesh degree):&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;$p$&lt;/th&gt;
      &lt;th&gt;$k = 6$&lt;/th&gt;
      &lt;th&gt;$k = 5$&lt;/th&gt;
      &lt;th&gt;$k = 4$&lt;/th&gt;
      &lt;th&gt;$k = 3$&lt;/th&gt;
      &lt;th&gt;$k = 2$&lt;/th&gt;
      &lt;th&gt;$k = 1$&lt;/th&gt;
      &lt;th&gt;$P(0)$&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0.05&lt;/td&gt;
      &lt;td&gt;0.037776&lt;/td&gt;
      &lt;td&gt;0.103617&lt;/td&gt;
      &lt;td&gt;0.239592&lt;/td&gt;
      &lt;td&gt;0.459467&lt;/td&gt;
      &lt;td&gt;0.720568&lt;/td&gt;
      &lt;td&gt;0.923055&lt;/td&gt;
      &lt;td&gt;0.076945&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.08&lt;/td&gt;
      &lt;td&gt;0.208126&lt;/td&gt;
      &lt;td&gt;0.371050&lt;/td&gt;
      &lt;td&gt;0.574704&lt;/td&gt;
      &lt;td&gt;0.774026&lt;/td&gt;
      &lt;td&gt;0.917288&lt;/td&gt;
      &lt;td&gt;0.984534&lt;/td&gt;
      &lt;td&gt;0.015466&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.10&lt;/td&gt;
      &lt;td&gt;0.383877&lt;/td&gt;
      &lt;td&gt;0.568802&lt;/td&gt;
      &lt;td&gt;0.749706&lt;/td&gt;
      &lt;td&gt;0.888271&lt;/td&gt;
      &lt;td&gt;0.966214&lt;/td&gt;
      &lt;td&gt;0.994846&lt;/td&gt;
      &lt;td&gt;0.005154&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.125&lt;/td&gt;
      &lt;td&gt;0.606513&lt;/td&gt;
      &lt;td&gt;0.765366&lt;/td&gt;
      &lt;td&gt;0.886232&lt;/td&gt;
      &lt;td&gt;0.958237&lt;/td&gt;
      &lt;td&gt;0.989739&lt;/td&gt;
      &lt;td&gt;0.998740&lt;/td&gt;
      &lt;td&gt;0.001260&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;0.15&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;0.780647&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;0.887895&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;0.953953&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;0.985811&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;0.997095&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;0.999704&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;0.000296&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.20&lt;/td&gt;
      &lt;td&gt;0.951973&lt;/td&gt;
      &lt;td&gt;0.981504&lt;/td&gt;
      &lt;td&gt;0.994344&lt;/td&gt;
      &lt;td&gt;0.998715&lt;/td&gt;
      &lt;td&gt;0.999807&lt;/td&gt;
      &lt;td&gt;0.999986&lt;/td&gt;
      &lt;td&gt;0.000014&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Secondary reliability.&lt;/strong&gt; Probability that a payload can be reconstructed from partial availability when primary reliability fails. Let $Y$ be the number of distinct columns available from sampler peers. Given $k$ provider peers that failed to serve the full payload, a node with $D - k$ sampler peers (each holding 8 random columns, assuming they’re all minimal custody full nodes) can reconstruct with probability $P(Y \geq 64 \mid n = D - k)$. For the adversarial scenario where we attained $k = 3$, yet all failed to serve the blob data, with $D = 50$, secondary reliability exceeds 99.9% as samplers provide an expected 124 distinct columns from 47 peers.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Providers ($k$)&lt;/th&gt;
      &lt;th&gt;Samplers ($n=D-k$)&lt;/th&gt;
      &lt;th&gt;$E[Distinct Columns]$&lt;/th&gt;
      &lt;th&gt;$P(Y ≥ 64)$&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;50&lt;/td&gt;
      &lt;td&gt;125.1&lt;/td&gt;
      &lt;td&gt;&amp;gt;99.99%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;49&lt;/td&gt;
      &lt;td&gt;124.9&lt;/td&gt;
      &lt;td&gt;&amp;gt;99.99%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;48&lt;/td&gt;
      &lt;td&gt;124.6&lt;/td&gt;
      &lt;td&gt;&amp;gt;99.99%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;47&lt;/td&gt;
      &lt;td&gt;124.3&lt;/td&gt;
      &lt;td&gt;&amp;gt;99.99%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;46&lt;/td&gt;
      &lt;td&gt;124.0&lt;/td&gt;
      &lt;td&gt;&amp;gt;99.99%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;…&lt;/td&gt;
      &lt;td&gt;…&lt;/td&gt;
      &lt;td&gt;…&lt;/td&gt;
      &lt;td&gt;…&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;~40&lt;/td&gt;
      &lt;td&gt;~10&lt;/td&gt;
      &lt;td&gt;~68&lt;/td&gt;
      &lt;td&gt;~80%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Minimum threshold&lt;/strong&gt;: Approximately $n_{\min} \approx 10$ samplers needed for reasonable reconstruction probability (&amp;gt;80%).&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP changes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth&lt;/code&gt; protocol and requires rolling out a new version, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/72&lt;/code&gt;. Supporting multiple versions of a wire protocol is possible. Rolling out a new version does not break older clients immediately, since they can keep using protocol version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/71&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This EIP does not change consensus rules and does not strictly require a hard fork. We are assessing the gradual rollout possibilities. In the meantime, it is RECOMMENDED that this EIP be deployed within the context of a hard fork.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;TBD&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;attack-scenarios-and-threat-model&quot;&gt;Attack scenarios and threat model&lt;/h3&gt;

&lt;p&gt;The goal of threat modeling is to identify potential attack vectors and vulnerabilities in the proposed sparse blobpool mechanism that may hurt the security, availability, or integrity of the type 3 transaction propagation. The threat model assumes a permissionless environment where adversaries can freely join the network, create multiple identities (Sybil attacks), and behave maliciously. Adversaries may aim to disrupt the network, degrade performance, censor transactions, or manipulate the availability of blob data. Below are some potential attack scenarios and their implications:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DoS attacks.&lt;/strong&gt; An important consideration in all mempool sharding mechanisms is the possibility of DoS attacks. This refers to the case where a malicious sender posts a transaction to the mempool disclosing only part of it, which makes the transaction impossible to be included in any future block, while still consuming mempool resources. In this system, such a sender can be detected by nodes that request the full payload of the transaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Selective withholding attacks.&lt;/strong&gt; A malicious peer might selectively withhold full blob data for certain type 3 transactions (e.g. produced by a certain L2), thus slowing down their propagation and potentially leading to reduced availability. This can be mitigated by ensuring a sufficiently large and diverse peerset.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eclipse attacks.&lt;/strong&gt; Malicious peers can try to isolate a victim node by controlling all its connections, serving only partial blob data and preventing it from obtaining the full payload. This hurts the victim’s ability to propagate transactions and can lead to reduced availability of blob data and potential censorship of the honest peer. However, periodic rotation of connections and keeping track of neighbor peer’s rate of full payload announcements can help mitigate this attack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free rider attacks.&lt;/strong&gt; A peer can send an excessive volume of blob data requests without reciprocating with announcements, thus consuming bandwidth without contributing to the network. This can be mitigated by keeping track of the requests to announcements ratio of peers and disconnecting those that exceed a certain threshold.&lt;/p&gt;

&lt;h3 id=&quot;peer-disconnection-policies&quot;&gt;Peer disconnection policies&lt;/h3&gt;

&lt;p&gt;Nodes MAY keep a record of the frequency of full payload and column requests made by each peer. If a frequency exceeds some quota or the probabilistic expectation by some tolerance threshold, the node MAY decide to disconnect the offending peer alleging abuse as a reason. This prevents nodes from spending too much upload bandwidth on peers that fetch full payloads much more often that the expected p = 0.15.&lt;/p&gt;

&lt;h3 id=&quot;the-need-for-sampling-noise&quot;&gt;The need for sampling noise&lt;/h3&gt;

&lt;p&gt;Custody-aligned sampling generates in stable and predictable request patterns that attackers could game. For example, a malicious node may trick a victim by pretending to be a provider when in reality it only stores the few, predictable columns the victim is expected to sample. To defend against this, this EIP introduces the simple mechanism of “sampling noise.”&lt;/p&gt;

&lt;p&gt;When a peer requests its custody columns from a provider, it must also request at least ONE randomly selected column. A failure to serve this extra column can be interpreted as a strong sign of misbehavior. The attacker could choose to timeout, but after a number of repetitions, the victim would likely disconnect anyway due to high failure rates.&lt;/p&gt;

&lt;p&gt;This simple mechanism reinforces key model assumptions (a provider is truly a provider) in exchange for negligible overhead per request (MAX_BLOBS_PER_TX x CELL_SIZE + proofs = ~12KiB).&lt;/p&gt;

&lt;h3 id=&quot;no-normative-peer-scoring&quot;&gt;No normative peer scoring&lt;/h3&gt;

&lt;p&gt;An earlier design considered a peer scoring system to grade peers by tracking their statistical ratio of requests to announcements (leechiness vs. helpfulness). After careful consideration, we deemed this approach brittle and dropped the feature. Our rationale was that such mechanism would strongly encode assumptions and confine the system to conform to some modellic behaviour, thus reducing flexibility and resilience in the face of environmental changes, shocks, or unexpected/improbable events (properties that are crucial in open and permissionless systems). Instead, we defer to implementations to define their own local heuristics for peer disconnection, if any.&lt;/p&gt;

&lt;h3 id=&quot;devp2p-message-schema-choices&quot;&gt;devp2p message schema choices&lt;/h3&gt;

&lt;p&gt;We note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cell_mask&lt;/code&gt; field in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewPooledTransactionHashes&lt;/code&gt; is not expressive enough to signal different local availability for type 3 txs announced within the same message. This limitation implies that (a) fully and partially available txs cannot be announced together, and (b) availability of randomly sampled columns cannot be signaled in practice (because indices vary per tx), only custody columns can be consistently announced (they’re shared across all sampled transactions).&lt;/p&gt;

&lt;p&gt;Nevertheless, the sender can efficiently split and group announcements: fully-available txs can be bundled together, and partially-available txs can be announced in separate messages. Per-message dispatch overhead is minimal (one uint64 request_id and one uint8 message_type), and more expressive designs are likely to incur in higher overhead. Furthermore, from a protocol flow perspective, devp2p supports concurrent requests and unordered responses (via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;request_id&lt;/code&gt; correlation), so this approach is not affected by head-of-line blocking either (at least from a protocol perspective).&lt;/p&gt;

&lt;p&gt;We considered more expressive designs, ranging from simple arrays of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cell_mask&lt;/code&gt;s (one per tx), to union types express full availability more compactly, to more complex schemes involving run-length encoding and compression. But we concluded that the added complexity was not justified at this time.&lt;/p&gt;

&lt;h3 id=&quot;open-points&quot;&gt;Open points&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Further threat modelling and security hardening.&lt;/li&gt;
  &lt;li&gt;RBF (replace-by-fee) impact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Wed, 29 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8070</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8070</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Cell-Level Deltas for Data Column Broadcast</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8136 - Cell-Level Deltas for Data Column Broadcast&lt;/strong&gt; is in Last Call status. It is authored by Marco Munizaga (@MarcoPolo) &lt;git@marcopolo.io&gt;, Daniel Knopik (@dknopik) &lt;daniel@dknopik.de&gt;, Sukun Tarachandani (@sukunrt) &lt;sukunrt@gmail.com&gt;, Aarsh Shah (@aarshkshah1992) &lt;aarshkshah1992@gmail.com&gt; and was originally created 2025-01-23. It is in the Networking category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8136-cell-level-deltas-for-data-column-broadcast/27675&quot;&gt;https://ethereum-magicians.org/t/eip-8136-cell-level-deltas-for-data-column-broadcast/27675&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;Cell-Level Deltas for Data Column Broadcast optimizes PeerDAS (&lt;a href=&quot;/EIPS/eip-7594&quot;&gt;EIP-7594&lt;/a&gt;) by
allowing more efficient transfers of blob data columns across the network.
Instead of having to exchange full data columns, peers exchange only the cells
they need within a column. This becomes especially useful when the majority of
cells within a column are already present from the local mempool. This
optimization is backwards compatible and can be progressively deployed. It does
not require a hard fork. Nodes that do not implement this optimization still
receive and transmit full data columns.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;In the vast majority of cases, all or nearly all blobs referenced in a block are
available in the mempool. Leveraging the blob data a node already has locally
lets a node avoid wasting bandwidth for cells it already has. In the current
design, if even a single blob is not present in the local mempool, the Consensus
Layer will have to wait to receive the full data column from the network before
passing its data availability checks. With this optimization, the client need
only wait to receive the missing cells.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cell-Level Deltas uses Gossipsub’s Partial Messages Extension to
exchange cell bitmaps and request/provide cells.&lt;/p&gt;

&lt;p&gt;In an effort to maintain a single source of truth, the specification is defined
in the &lt;a href=&quot;https://github.com/ethereum/consensus-specs/tree/b3b06d939c3f7301d218bca7adc39eed5806d553/./&quot;&gt;ethereum/consensus-specs&lt;/a&gt; repo.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;The design is guided by two main factors:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Minimal semantic changes.&lt;/li&gt;
  &lt;li&gt;Backwards compatible (no hard fork required).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These two factors lead the design into something that extends the existing
gossipsub behavior rather than introducing a new protocol. The mesh and gossip
properties of gossipsub are unchanged. If a node’s gossipsub peers support this
extension they can both make use of it. Otherwise, the behavior falls back to
traditional gossipsub.&lt;/p&gt;

&lt;p&gt;The biggest difference the extension introduces is defaulting to a pull-based
dissemination strategy of cells rather than a push based one. Eager pushing of
data is still possible, but it is not the default behavior.&lt;/p&gt;

&lt;h3 id=&quot;alternative-designs&quot;&gt;Alternative Designs&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Smaller gossipsub messages.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This design makes the gossipsub message unit be a single cell rather than a full
column. While it would transfer data at the cell level, without having bitmaps
as a first class concept it would introduce overhead for a cell per message.
Furthermore, informing peers about cells a node has (via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IDONTWANT&lt;/code&gt;) would always
race against the peers pushing the same cells to the node. The default-push
strategy is too aggressive for the case when almost all blobs are public. The
message ID is content based (e.g. a hash), and lacks context as to what block
this cell is part of, making it impossible for a node to request cells it
doesn’t have or prioritize cells from a block it’s processing.&lt;/p&gt;

&lt;p&gt;Changing the semantics of the message ID may be possible as a workaround for
some of the above issues, but this would still require a separate gossipsub
topic that could not be used as a backwards compatible replacement to the
existing gossipsub topic. Changing message ID semantics may also break gossipsub
implementations that assume a message ID and message are 1:1.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A new RPC method.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This seems like the simplest option at first glance, but it ignores the work
already happening in gossipsub. If we merely add a new RPC method with no
gossipsub changes, we risk only increasing network and compute load rather than
reducing it. Because we are now doing an extra RPC on top of existing gossipsub
work. To fix this, gossipsub and the RPC method need to be cognizant of each
other. Eventually this leads to the proposed design, a gossipsub extension of
partial messages with application defined semantics.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A new protocol separate from gossipsub.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While this may be a long term direction worth exploring, this is deemed too big
a change to make to leverage this optimization. Especially if we’d like to
deploy this without a hard fork.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;No backward compatibility issues.&lt;/p&gt;

&lt;p&gt;Nodes form gossipsub meshes and gossip with the same rules as before. This
optimization only takes effect when both nodes in a gossipsub exchange support
this extension. If either side does not support this extension, both nodes
behave the same as before, exchanging full gossipsub messages to each other.&lt;/p&gt;

&lt;p&gt;Gossipsub scores peers well if they provide timely messages, and penalizes peers
if they provide invalid messages. This extension does not change that, peer
scores should behave the same with and without this extension.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;In the default case, this adds minor latency to cell dissemination compared to
the standard gossipsub’s default push behavior in exchange for more efficient
bandwidth usage. However, over time the eager cell push policy of nodes can be
refined to match and even improve dissemination latency. This latency is a key
metric that will be monitored during and after rollout.&lt;/p&gt;

&lt;p&gt;There are also a couple implementation specific pitfalls client implementers and
gossipsub implementers should be aware of.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;While it is more efficient for a node to mesh with peers that support this
EIP, it risks dividing the network if those peers are preferred.
Implementations SHOULD NOT discriminate against peers that do not support
this extension.&lt;/li&gt;
  &lt;li&gt;Related to the above, a peer’s score should be roughly equivalent whether
they support partial messages or not. A peer should not score higher if they
provide cells one at a time versus all at once.&lt;/li&gt;
  &lt;li&gt;Implementations should be resilient to peers spamming messages with
different Group IDs. Implementations SHOULD reserve space for mesh peer
messages in case of adversarial non-mesh peers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This optimization is expected to roll out gradually with the ability to roll
back if needed.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Thu, 23 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8136</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8136</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Facet-Based Diamonds</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8153 - Facet-Based Diamonds&lt;/strong&gt; is in Last Call status. It is authored by Nick Mudge (@mudgen) and was originally created 2026-02-07. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8153-facet-based-diamonds/27685&quot;&gt;https://ethereum-magicians.org/t/erc-8153-facet-based-diamonds/27685&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;A diamond is a proxy contract that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s to multiple implementation contracts called facets.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/eip-8153/basic-diamond-diagram.svg&quot; alt=&quot;Diagram showing how a diamond contract works&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Diamond contracts were originally standardized by &lt;a href=&quot;/EIPS/eip-2535&quot;&gt;ERC-2535&lt;/a&gt;. This ERC builds on that foundation by defining a facet-based architecture in which facets self-describe their function selectors through a standardized introspection interface.&lt;/p&gt;

&lt;p&gt;By moving selector discovery on-chain, this approach eliminates the need for off-chain selector management. As a result, diamond deployment and upgrades become simpler, more deterministic, and more gas efficient.&lt;/p&gt;

&lt;p&gt;This ERC introduces a facet introspection function, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt;, which every facet MUST implement. This function returns the list of function selectors implemented by the facet, allowing a diamond to discover and register selectors on-chain during deployment or upgrade.&lt;/p&gt;

&lt;p&gt;This ERC also defines facet-based events for adding, replacing, and removing facets.&lt;/p&gt;

&lt;p&gt;Additionally, the ERC defines an optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; function. This function uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; to automatically determine which selectors should be added, replaced, or removed when applying facet changes.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;h3 id=&quot;motivation-for-diamond-contracts&quot;&gt;Motivation for Diamond Contracts&lt;/h3&gt;

&lt;p&gt;&lt;img alt=&quot;Obligatory diamond&quot; src=&quot;../assets/eip-8153/diamond.svg&quot; width=&quot;17%&quot; align=&quot;right&quot; /&gt;Through a single contract address, a diamond provides functionality from multiple implementation contracts (facets). Each facet is independent, yet facets can share internal functions and storage. This architecture allows large smart-contract systems to be composed from separate facets and presented as a single contract, simplifying deployment, testing, and integration with other contracts, off-chain software, and user interfaces.&lt;/p&gt;

&lt;p&gt;By decomposing large smart contracts into facets, diamonds can reduce complexity and make systems easier to reason about. Distinct areas of functionality can be isolated, organized, tested, and managed independently.&lt;/p&gt;

&lt;p&gt;Diamonds combine the single-address convenience of a monolithic contract with the modular flexibility of distinct, integrated contracts.&lt;/p&gt;

&lt;p&gt;This architecture is well suited to &lt;strong&gt;immutable&lt;/strong&gt; smart-contract systems, where all functionality is composed from multiple facets at deployment time and permanently fixed thereafter.&lt;/p&gt;

&lt;p&gt;For upgradeable systems, diamonds enable incremental development: new functionality can be added, and existing functionality modified, without redeploying unaffected facets.&lt;/p&gt;

&lt;p&gt;Additional motivation and background for diamond-based smart-contract systems can be found in &lt;a href=&quot;/EIPS/eip-1538&quot;&gt;ERC-1538&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-2535&quot;&gt;ERC-2535&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;motivation-for-this-standard&quot;&gt;Motivation for this Standard&lt;/h3&gt;

&lt;p&gt;In the past, deploying and upgrading diamonds suffered from:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;High gas costs&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Function selector management complexity&lt;/strong&gt;
Deploying or upgrading a diamond requires assembling function selectors off-chain. Since common tooling (e.g., Hardhat, Foundry) does not natively manage diamond selectors, developers rely on custom scripts or third-party libraries to handle diamond “plumbing”.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This standard reduces gas costs and eliminates off-chain selector management:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Diamonds become less expensive to deploy.&lt;/li&gt;
  &lt;li&gt;Function selectors no longer need to be gathered off-chain.&lt;/li&gt;
  &lt;li&gt;Standard deployment tools can be used without special diamond support.&lt;/li&gt;
  &lt;li&gt;ERC-2535 introspection functions have simple implementations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;terms&quot;&gt;Terms&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;A &lt;strong&gt;diamond&lt;/strong&gt; is a smart contract that routes external function calls to one or more implementation contracts, referred to as facets. A diamond is stateful: all persistent data is stored in the diamond’s contract storage. A diamond implements the requirements in the &lt;a href=&quot;#implementation-requirements&quot;&gt;Implementation Requirements&lt;/a&gt; section.&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;facet&lt;/strong&gt; is a smart contract that defines one or more external functions. A facet is deployed independently, and one or more of its functions are added to one or more diamonds. A facet’s functions are executed in the diamond’s context via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;, so reads/writes affect the diamond’s storage. The term facet is derived from the diamond industry, referring to a flat surface of a diamond.&lt;/li&gt;
  &lt;li&gt;An &lt;strong&gt;introspection function&lt;/strong&gt; is a function that returns information about the facets and/or functions used by a diamond or facet.&lt;/li&gt;
  &lt;li&gt;For the purposes of this specification, a &lt;strong&gt;mapping&lt;/strong&gt; refers to a conceptual association between two items and does not refer to a specific implementation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;diamond-diagram&quot;&gt;Diamond Diagram&lt;/h3&gt;

&lt;p&gt;This diagram shows the structure of a diamond.&lt;/p&gt;

&lt;p&gt;It shows that a diamond has a mapping from function to facet and that facets can access the storage inside a diamond.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/eip-8153/functionFacetMapping.svg&quot; alt=&quot;Diagram showing structure of a diamond&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fallback&quot;&gt;Fallback&lt;/h3&gt;

&lt;p&gt;When an external function is called on a diamond, its fallback function is executed. The fallback function determines which facet to call based on the first four bytes of the calldata (known as the function selector) and executes the function from the facet using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A diamond’s fallback function and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; enable a diamond to execute a facet’s function as if it were implemented by the diamond itself. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.value&lt;/code&gt; values do not change and only the diamond’s storage is read and written to.&lt;/p&gt;

&lt;p&gt;Here is an example of how a diamond’s fallback function might be implemented:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FunctionNotFound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Executes function call on facet using `delegatecall`.
// Returns function call return data or revert data.
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Get facet address from function selector
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;selectorToFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;revert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FunctionNotFound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Execute external function on facet using `delegatecall` and return any value.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Copy function selector and any arguments from calldata to memory.
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;calldatacopy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calldatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Execute function call using the facet.
&lt;/span&gt;        &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;delegatecall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calldatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Copy all return data from the previous call into memory.
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;returndatacopy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Return any return value or error back to the caller.
&lt;/span&gt;        &lt;span class=&quot;kr&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;revert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())}&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;function-not-found&quot;&gt;Function Not Found&lt;/h4&gt;

&lt;p&gt;If the fallback function cannot find a facet for a function selector, and there is no default function or other mechanism to handle the call, the fallback MUST revert with the error &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FunctionNotFound(bytes4 _selector)&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;inspecting-diamonds&quot;&gt;Inspecting Diamonds&lt;/h3&gt;

&lt;p&gt;A diamond implementing this standard MUST implement the same introspection functions as defined in ERC-2535.
Specifically, these functions MUST be implemented:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDiamondInspect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Facet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functionSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Gets all facet addresses and their four byte function selectors.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return facets_ Facet
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facets_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Gets all the function selectors supported by a specific facet.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param _facet The facet address.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return facetFunctionSelectors_
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetFunctionSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetFunctionSelectors_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Get all the facet addresses used by a diamond.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return facetAddresses_
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddresses_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Gets the facet that supports the given selector.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @dev If facet is not found return address(0).
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param _functionSelector The function selector.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return facetAddress_ The facet address.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_functionSelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Typically, these functions are implemented in a facet and the facet is added to diamonds.&lt;/p&gt;

&lt;h3 id=&quot;inspecting-facets&quot;&gt;Inspecting Facets&lt;/h3&gt;

&lt;p&gt;Each facet MUST implement the following pure introspection function:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IFacet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exportSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;selectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; array containing one or more 4-byte function selectors. The returned &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; array length MUST be a multiple of 4, and each 4-byte chunk is a selector. The function MUST NOT return a specific selector more than once.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; array contains selectors of functions implemented by the facet that are intended to be added to a diamond.&lt;/p&gt;

&lt;p&gt;This enables a diamond to discover selectors directly from facets at deployment or upgrade time. A diamond calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on each facet to determine which selectors to add, replace, or remove.&lt;/p&gt;

&lt;p&gt;Selector gathering is therefore no longer an off-chain responsibility.&lt;/p&gt;

&lt;p&gt;This also means diamonds implementing this ERC are &lt;strong&gt;facet-based&lt;/strong&gt; rather than &lt;strong&gt;function-based&lt;/strong&gt;. Deployment and upgrades operate on facets.&lt;/p&gt;

&lt;h3 id=&quot;facet-based-events&quot;&gt;Facet-Based Events&lt;/h3&gt;

&lt;p&gt;This ERC replaces ERC-2535’s function-based events with facet-based events.&lt;/p&gt;

&lt;p&gt;When facets are added, replaced, or removed, the diamond MUST emit the following events:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;cm&quot;&gt;/**
  * @notice Emitted when a facet is added to a diamond.
  * @dev The function selectors this facet handles can be retrieved by calling
  *      `IFacet(_facet).exportSelectors()`
  *
  * @param _facet The address of the facet that handles function calls to the diamond.
  */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetAdded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @notice Emitted when an existing facet is replaced with a new facet.
 * @dev
 * - Selectors that are present in the new facet but not in the old facet are added to the diamond.
 * - Selectors that are present in both the new and old facet are updated to use the new facet.
 * - Selectors that are not present in the new facet but are present in the old facet are removed from
 *   the diamond.
 *
 * The function selectors handled by these facets can be retrieved by calling:
 * - `IFacet(_oldFacet).exportSelectors()`
 * - `IFacet(_newFacet).exportSelectors()`
 *
 * @param _oldFacet The address of the facet that previously handled function calls to the diamond.
 * @param _newFacet The address of the facet that now handles function calls to the diamond.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetReplaced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_oldFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_newFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @notice Emitted when a facet is removed from a diamond.
 * @dev The function selectors this facet handles can be retrieved by calling
 *      `IFacet(_facet).exportSelectors()`
 *
 * @param _facet The address of the facet that previously handled function calls to the diamond.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetRemoved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Block explorers and other tooling can obtain the function selectors for any of the facets referenced by these events by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the facet address.&lt;/p&gt;

&lt;h3 id=&quot;optional-events&quot;&gt;Optional Events&lt;/h3&gt;

&lt;h4 id=&quot;recording-non-fallback-delegatecalls&quot;&gt;Recording Non-Fallback &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s&lt;/h4&gt;

&lt;p&gt;This event is OPTIONAL, except &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; functions MUST emit it as specified in this standard.&lt;/p&gt;

&lt;p&gt;This event can be used to record &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s made by a diamond.&lt;/p&gt;

&lt;p&gt;This event MUST NOT be emitted for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s made by a diamond’s fallback function when routing calls to facets. It is only intended for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s made by functions in facets or a diamond’s constructor.&lt;/p&gt;

&lt;p&gt;This event enables tracking of changes to a diamond’s contract storage caused by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; execution.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
* @notice Emitted when a diamond&apos;s constructor or function from a
*         facet makes a `delegatecall`. 
* 
* @param _delegate         The contract that was the target of the `delegatecall`.
* @param _delegateCalldata The function call, including function selector and 
*                          any arguments.
*/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DiamondDelegateCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegateCalldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;diamond-metadata&quot;&gt;Diamond Metadata&lt;/h4&gt;

&lt;p&gt;This event is OPTIONAL, except &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; functions MUST emit it as specified in this standard.&lt;/p&gt;

&lt;p&gt;This event can be used to record versioning or other information about diamonds.&lt;/p&gt;

&lt;p&gt;It can be used to record information about diamond upgrades.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
* @notice Emitted to record information about a diamond.
* @dev    This event records any arbitrary metadata. 
*         The format of `_tag` and `_data` are not specified by the 
*         standard.
*
* @param _tag   Arbitrary metadata, such as a release version.
* @param _data  Arbitrary metadata.
*/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DiamondMetadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;implementation-requirements&quot;&gt;Implementation Requirements&lt;/h3&gt;

&lt;p&gt;A facet-based diamond MUST implement the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Diamond Structure&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fallback()&lt;/code&gt; function.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Function Association&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;It MUST associate function selectors with facet addresses.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Function Execution&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;When an external function is called on a diamond:
        &lt;ul&gt;
          &lt;li&gt;The diamond’s fallback function is executed.&lt;/li&gt;
          &lt;li&gt;The fallback function MUST find the facet associated with the function selector.&lt;/li&gt;
          &lt;li&gt;The fallback function MUST execute the function on the facet using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;If no facet is associated with the function selector, the diamond MAY execute a default function or apply another handling mechanism.&lt;/li&gt;
          &lt;li&gt;If no facet, default function, or other handling mechanism exists, execution MUST revert with the error &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FunctionNotFound(bytes4 _selector)&lt;/code&gt;.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Events&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;The following events MUST be emitted:
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetAdded&lt;/code&gt; — when a facet is added to a diamond.&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetReplaced&lt;/code&gt; — when a facet is replaced with a different facet.&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetRemoved&lt;/code&gt; — when a facet is removed from a diamond.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Diamond Introspection&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;A diamond MUST implement the following introspection functions:
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;facets()&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;facetFunctionSelectors(address _facet)&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;facetAddresses()&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;facetAddress(bytes4 _functionSelector)&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Facet Introspection&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Each facet MUST implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; function, which returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; array.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;receive-function&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive()&lt;/code&gt; Function&lt;/h3&gt;

&lt;p&gt;A diamond MAY have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive()&lt;/code&gt; function.&lt;/p&gt;

&lt;h3 id=&quot;upgradediamond-function&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; Function&lt;/h3&gt;

&lt;p&gt;Implementing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; is OPTIONAL.&lt;/p&gt;

&lt;p&gt;This function is specified for interoperability with tooling (e.g., GUIs and command-line tools) so that upgrades can be executed with consistent and predictable behavior.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; adds, replaces, and removes any number of facets in a single transaction. It can also optionally execute a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; to perform initialization or state migration.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; function works as follows:&lt;/p&gt;

&lt;h4 id=&quot;adding-a-facet&quot;&gt;Adding a Facet&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the facet to obtain its function selectors.&lt;/li&gt;
  &lt;li&gt;Add each selector to the diamond, mapping it to the facet address.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;replacing-a-facet&quot;&gt;Replacing a Facet&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the old facet to obtain its function selectors.&lt;/li&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the new facet to obtain its function selectors.&lt;/li&gt;
  &lt;li&gt;For selectors present in the new facet but not the old facet: add them.&lt;/li&gt;
  &lt;li&gt;For selectors present in both: replace them to point to the new facet.&lt;/li&gt;
  &lt;li&gt;For selectors present in the old facet but not the new facet: remove them.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;removing-a-facet&quot;&gt;Removing a Facet&lt;/h4&gt;
&lt;ol&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the facet to obtain its function selectors.&lt;/li&gt;
  &lt;li&gt;Remove each selector from the diamond.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;errors-and-types&quot;&gt;Errors and Types&lt;/h4&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
 * @notice The upgradeDiamond function below detects and reverts
 *         with the following errors.
 */&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NoSelectorsForFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NoBytecodeAtAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CannotAddFunctionToDiamondThatAlreadyExists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CannotRemoveFacetThatDoesNotExist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CannotReplaceFacetWithSameFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetToReplaceDoesNotExist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_oldFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DelegateCallReverted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegateCalldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExportSelectorsCallFailed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @dev This error means that a function to replace exists in a
 *      facet other than the facet that was given to be replaced.
 */&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CannotReplaceFunctionFromNonReplacementFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @notice This struct is used to replace old facets with new facets.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetReplacement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;function-signature&quot;&gt;Function Signature&lt;/h4&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
 * @notice Upgrade the diamond by adding, replacing, or removing facets.
 *
 * @dev
 * Facets are added first, then replaced, then removed.
 *
 * These events are emitted to record changes to facets:
 * - `FacetAdded(address indexed _facet)`
 * - `FacetReplaced(address indexed _oldFacet, address indexed _newFacet)`
 * - `FacetRemoved(address indexed _facet)`
 *
 * If `_delegate` is non-zero, the diamond performs a `delegatecall` to
 * `_delegate` using `_delegateCalldata`. The `DiamondDelegateCall` event is
 *  emitted.
 *
 * The `delegatecall` is done to alter a diamond&apos;s state or to
 * initialize, modify, or remove state after an upgrade.
 *
 * However, if `_delegate` is zero, no `delegatecall` is made and no
 * `DiamondDelegateCall` event is emitted.
 *
 * If _tag is non-zero or if _metadata.length &amp;gt; 0 then the
 * `DiamondMetadata` event is emitted.
 *
 * @param _addFacets        Facets to add.
 * @param _replaceFacets    (oldFacet, newFacet) pairs, to replace old with new.
 * @param _removeFacets     Facets to remove.
 * @param _delegate         Optional contract to delegatecall (zero address to skip).
 * @param _delegateCalldata Optional calldata to execute on `_delegate`.
 * @param _tag              Optional arbitrary metadata, such as release version.
 * @param _metadata         Optional arbitrary data.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgradeDiamond&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_addFacets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;FacetReplacement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_replaceFacets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_removeFacets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegateCalldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_metadata&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; function MUST adhere to the following requirements:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Definitions of events and custom errors referenced below are given earlier in this standard.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Inputs&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_addFacets&lt;/code&gt; array of facet addresses to add.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_replaceFacets&lt;/code&gt; array of (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldFacet&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newFacet&lt;/code&gt;) pairs.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_removeFacets&lt;/code&gt; array of facet addresses to remove.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Execution Order&lt;/strong&gt;
    &lt;ol&gt;
      &lt;li&gt;Add facets&lt;/li&gt;
      &lt;li&gt;Replace facets&lt;/li&gt;
      &lt;li&gt;Remove facets&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Event Emission&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Every change to a facet MUST emit exactly one of:
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetAdded&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetReplaced&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetRemoved&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Error Conditions&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;The implementation MUST detect and revert with the specified error when:
        &lt;ul&gt;
          &lt;li&gt;Adding a selector that already exists: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CannotAddFunctionToDiamondThatAlreadyExists&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;Removing a facet that does not exist: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CannotRemoveFacetThatDoesNotExist&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;Replacing a facet with itself: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CannotReplaceFacetWithSameFacet&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;Replacing a facet that does not exist: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetToReplaceDoesNotExist&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;Replacing a selector that exists in the diamond but is mapped to a facet different than the facet being replaced: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CannotReplaceFunctionFromNonReplacementFacet&lt;/code&gt;.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Facet Validation&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;If any facet address contains no contract bytecode, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NoBytecodeAtAddress&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; is missing, reverts, or cannot be called successfully, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExportSelectorsCallFailed&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; returns zero selectors, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NoSelectorsForFacet&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Delegate Validation&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegate&lt;/code&gt; is non-zero but contains no bytecode, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NoBytecodeAtAddress&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Delegatecall Execution&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegate&lt;/code&gt; is non-zero, the diamond MUST &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegate&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegateCalldata&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; fails and returns revert data, the diamond MUST revert with the same revert data.&lt;/li&gt;
      &lt;li&gt;If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; fails and returns no revert data, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DelegateCallReverted&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; is performed, the diamond MUST emit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DiamondDelegateCall&lt;/code&gt; event.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegateCalldata&lt;/code&gt; MAY be empty. If empty, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; executes with no calldata.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Metadata Event&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_tag&lt;/code&gt; is non-zero or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_metadata.length &amp;gt; 0&lt;/code&gt;, the diamond MUST emit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DiamondMetadata&lt;/code&gt; event.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After adding, replacing, or removing facets, the diamond MAY perform a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; to initialize, migrate, or clean up state.&lt;/p&gt;

&lt;p&gt;It is also valid to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; solely to perform a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; (i.e., without adding, replacing, or removing any facets).&lt;/p&gt;

&lt;p&gt;To skip an operation, supply an empty array for its parameter (for example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new address[](0)&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_addFacets&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;eliminating-selector-management&quot;&gt;Eliminating Selector Management&lt;/h3&gt;

&lt;p&gt;To deploy a facet-based diamond implementing this ERC, the deployer provides an array of facet addresses to the diamond constructor. The constructor calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on each facet and registers those selectors in the diamond.&lt;/p&gt;

&lt;p&gt;Because facets self-describe their selectors, deployers no longer need to gather selectors off-chain or depend on specialized selector tooling.&lt;/p&gt;

&lt;h3 id=&quot;reducing-deployment-gas-costs&quot;&gt;Reducing Deployment Gas Costs&lt;/h3&gt;

&lt;h4 id=&quot;reducing-calldata&quot;&gt;Reducing Calldata&lt;/h4&gt;

&lt;p&gt;In a non-facet-based diamond, selectors are typically passed to the constructor as one or more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[]&lt;/code&gt; arrays. These arrays are paid for in calldata and then copied into memory, incurring additional gas.&lt;/p&gt;

&lt;p&gt;In a facet-based diamond, only facet addresses are passed to constructors. The diamond calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on each facet to obtain selectors on-chain, avoiding calldata costs for selector lists. While calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; introduces some overhead, non-facet-based diamonds typically perform code-existence checks (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extcodesize&lt;/code&gt;) on facet addresses anyway, incurring the cold account access gas cost.&lt;/p&gt;

&lt;h4 id=&quot;reducing-storage&quot;&gt;Reducing Storage&lt;/h4&gt;

&lt;p&gt;In a &lt;strong&gt;non-facet-based diamond&lt;/strong&gt;, function selectors are stored directly for introspection, typically in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[] selectors&lt;/code&gt; array (or an equivalent structure). Because a storage slot is 32 bytes, each slot can hold up to eight &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4&lt;/code&gt; selectors. As more functions are added, additional storage slots are required, so storage usage grows linearly with the number of selectors.&lt;/p&gt;

&lt;p&gt;In a &lt;strong&gt;facet-based diamond&lt;/strong&gt;, introspection data can be stored &lt;strong&gt;per facet instead of per function&lt;/strong&gt;. Each facet only needs a single representative selector. This means one 32-byte storage slot can represent up to eight facets, regardless of how many function selectors each facet implements. Storage usage therefore grows with the number of facets, not the number of functions.&lt;/p&gt;

&lt;p&gt;Alternatively, a facet-based diamond can be implemented as a &lt;strong&gt;linked list of facets&lt;/strong&gt;. With this design, introspection requires a &lt;strong&gt;single 32-byte storage slot&lt;/strong&gt;, while supporting any number of facets and any number of selectors per facet.&lt;/p&gt;

&lt;h3 id=&quot;exportselectors-function-return-value&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; Function Return Value&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[]&lt;/code&gt; for two reasons:&lt;/p&gt;

&lt;h4 id=&quot;bytes4-wastes-memory&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[]&lt;/code&gt; Wastes Memory&lt;/h4&gt;

&lt;p&gt;Each element of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[]&lt;/code&gt; array occupies 32 bytes in memory, but only 4 bytes are meaningful. This wastes 87.5% of allocated memory, increasing gas costs. Packing selectors into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; reduces memory overhead.&lt;/p&gt;

&lt;h4 id=&quot;simple-syntax-for-facets&quot;&gt;Simple Syntax For Facets&lt;/h4&gt;

&lt;p&gt;Facets can implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; concisely using Solidity’s built-in function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes.concat&lt;/code&gt;. Example:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exportSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facetAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facetFunctionSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facetAddresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The diamond can traverse the returned bytes and extract selectors efficiently.&lt;/p&gt;

&lt;h3 id=&quot;diamond-upgrades&quot;&gt;Diamond Upgrades&lt;/h3&gt;

&lt;p&gt;The upgrade function specified by this standard is optional.&lt;/p&gt;

&lt;p&gt;This means a couple of things:&lt;/p&gt;

&lt;h4 id=&quot;1-diamonds-can-be-immutable&quot;&gt;1. Diamonds Can Be Immutable&lt;/h4&gt;

&lt;p&gt;A Diamond does not have to have an upgrade function.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A diamond can be fully constructed within its constructor without adding any upgrade function, making it immutable upon deployment.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A large immutable diamond can be built using well organized facets.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A diamond can initially be upgradeable, and later made immutable by removing its upgrade function.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;2-you-can-create-your-own-upgrade-functions&quot;&gt;2. You Can Create Your Own Upgrade Functions&lt;/h4&gt;

&lt;p&gt;You can design and create your own upgrade functions and remain compliant with this standard. All that is required is that you emit the appropriate add/replace/remove events specified in the &lt;a href=&quot;#facet-based-events&quot;&gt;Facet-Based Events section&lt;/a&gt;, and that the introspection functions defined in the &lt;a href=&quot;#inspecting-diamonds&quot;&gt;Inspecting Diamonds section&lt;/a&gt; and the &lt;a href=&quot;#inspecting-facets&quot;&gt;Inspecting Facets section&lt;/a&gt; continue to exist and accurately return function and facet information.&lt;/p&gt;

&lt;h3 id=&quot;runtime-gas-considerations&quot;&gt;Runtime Gas Considerations&lt;/h3&gt;

&lt;p&gt;Routing calls via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; introduces a small amount of gas overhead. In practice, this cost is mitigated by several architectural and tooling advantages enabled by diamonds:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Optional, gas-optimized functionality&lt;/strong&gt;&lt;br /&gt;
By structuring functionality across multiple facets, diamonds make it straightforward to include specialized, gas-optimized features without increasing the complexity of core logic.&lt;br /&gt;
For example, an &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt; diamond may implement batch transfer functions in a dedicated facet, improving both gas efficiency and usability while keeping the base ERC-721 implementation simple and well-scoped.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Reduced external call overhead&lt;/strong&gt;  &lt;br /&gt;
Some contract architectures require multiple external calls within a single transaction. By consolidating related functionality behind a single diamond address, these interactions can execute internally with shared storage and shared authorization, reducing gas costs from external calls and repeated access-control checks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Selective optimization per facet&lt;/strong&gt;&lt;br /&gt;
Because facets are compiled and deployed independently, they may be built with different compiler optimizer settings. This allows gas-critical facets to use aggressive optimization configurations to reduce execution costs, without increasing bytecode size or compilation complexity for unrelated functionality.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;storage-layout&quot;&gt;Storage Layout&lt;/h3&gt;

&lt;p&gt;Diamonds and facets need to use a storage layout organizational pattern because Solidity’s default storage layout doesn’t support proxy contracts or diamonds. The storage layout technique or pattern to use is not specified in this ERC. However, examples of storage layout patterns that work with diamonds are &lt;a href=&quot;/EIPS/eip-8042&quot;&gt;ERC-8042 Diamond Storage&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-7201&quot;&gt;ERC-7201 Namespaced Storage Layout&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;facets-sharing-storage--functionality&quot;&gt;Facets Sharing Storage &amp;amp; Functionality&lt;/h3&gt;

&lt;p&gt;Facets are separately deployed, independent units, but can share state and functionality in the following ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Facets can share state variables by using the same structs at the same storage positions.&lt;/li&gt;
  &lt;li&gt;Facets can share internal functions by importing them or inheriting contracts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;on-chain-facets-can-be-reused-and-composed&quot;&gt;On-chain Facets can be Reused and Composed&lt;/h3&gt;

&lt;p&gt;A deployed facet can be used by many diamonds.&lt;/p&gt;

&lt;p&gt;It is possible to create and deploy a set of facets that are reused by different diamonds.&lt;/p&gt;

&lt;p&gt;The ability to use the same deployed facets for many diamonds has the potential to reduce development time, increase reliability and security, and reduce deployment costs.&lt;/p&gt;

&lt;p&gt;It is possible to implement facets in a way that makes them usable/composable/compatible with other facets.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;Diamonds implementing this ERC have the same introspection functions as ERC-2535 diamonds, so they are compatible with ERC-2535 tooling that relies on these functions.&lt;/p&gt;

&lt;p&gt;This ERC breaks compatibility with ERC-2535 events and upgrades.&lt;/p&gt;

&lt;p&gt;Facets deployed for ERC-2535 diamonds cannot be used with ERC-8153 diamonds if they do not have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; function.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;arbitrary-execution-with-upgradediamond&quot;&gt;Arbitrary Execution with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; function allows arbitrary execution with access to the diamond’s storage (through delegatecall). Access to this function must be restricted carefully.&lt;/p&gt;

&lt;h3 id=&quot;use-only-trusted-and-verified-facets&quot;&gt;Use Only Trusted and Verified Facets&lt;/h3&gt;

&lt;p&gt;Only trusted and verified facets should be added to facet-based diamonds.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pure&lt;/code&gt; and should not contain logic that varies the returned bytes. Facets should be immutable so returned selectors cannot change over time.&lt;/p&gt;

&lt;p&gt;If a facet’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; output changes, upgrades that rely on it may add/remove/replace the wrong selectors and corrupt diamonds.&lt;/p&gt;

&lt;h3 id=&quot;upgrade-integrity-checks&quot;&gt;Upgrade Integrity Checks&lt;/h3&gt;

&lt;p&gt;The specified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; behavior prevents a number of upgrade mistakes. Upgrades revert when:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A facet is added that already exists in the diamond.&lt;/li&gt;
  &lt;li&gt;A facet is replaced or removed that does not exist in the diamond.&lt;/li&gt;
  &lt;li&gt;A selector is added that already exists in the diamond.&lt;/li&gt;
  &lt;li&gt;A selector is replaced that exists in the diamond but is mapped to a different facet than the facet being replaced.&lt;/li&gt;
  &lt;li&gt;A facet address contains no bytecode.&lt;/li&gt;
  &lt;li&gt;A facet does not implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; successfully.&lt;/li&gt;
  &lt;li&gt;A facet provides zero selectors.&lt;/li&gt;
  &lt;li&gt;A facet is replaced with itself (same contract address).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Selector collisions (two different signatures with the same 4-byte selector) are handled as “selector already exists” and are therefore prevented.&lt;/p&gt;

&lt;h3 id=&quot;do-not-self-destruct&quot;&gt;Do Not Self Destruct&lt;/h3&gt;
&lt;p&gt;Use of selfdestruct in a facet is heavily discouraged. Misuse of it can delete a diamond or a facet.&lt;/p&gt;

&lt;h3 id=&quot;transparency&quot;&gt;Transparency&lt;/h3&gt;

&lt;p&gt;A diamond emits an event every time a facet is added, replaced or removed. Source code can be verified. This enables people and software to monitor changes to a diamond.&lt;/p&gt;

&lt;p&gt;Security and domain experts can review a diamond’s upgrade history.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sat, 07 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8153</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8153</guid>
      </item>
      
    
      
      
      <item>
        <title>eth/71 - Block Access List Exchange</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8159 - eth/71 - Block Access List Exchange&lt;/strong&gt; is in Last Call status. It is authored by Toni Wahrstätter (@nerolation) and was originally created 2026-02-12. It is in the Networking category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8159-eth-71-block-access-list-exchange/27725&quot;&gt;https://ethereum-magicians.org/t/eip-8159-eth-71-block-access-list-exchange/27725&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP modifies the ‘eth’ p2p protocol to support Block-level Access Lists (BALs). It adds two new messages, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetBlockAccessLists&lt;/code&gt; (0x12) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockAccessLists&lt;/code&gt; (0x13), enabling peers to request and serve BALs for synchronization and parallel execution.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; introduces block-level access lists that record all state locations accessed during block execution. These lists enable parallel disk reads, parallel transaction execution, and executionless state updates.&lt;/p&gt;

&lt;p&gt;For syncing clients to leverage these capabilities, BALs must be obtainable from peers. The Engine API provides BALs from the consensus layer during normal operation, but historical BALs and peer-based sync require wire protocol support.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;block-header-extension&quot;&gt;Block Header Extension&lt;/h3&gt;

&lt;p&gt;The block header is extended with a new field after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requests-hash&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;block-header = [
    ...
    requests-hash: B_32,
    block-access-list-hash: B_32,
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block-access-list-hash&lt;/code&gt; field contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(rlp.encode(block-access-list))&lt;/code&gt; as defined in &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;. This field MUST be present in headers after the Amsterdam fork and absent for earlier blocks.&lt;/p&gt;

&lt;h3 id=&quot;block-access-list-encoding&quot;&gt;Block Access List Encoding&lt;/h3&gt;

&lt;p&gt;BALs are RLP-encoded as a list of account changes, sorted lexicographically by address:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;block-access-list = [account-changes₁, account-changes₂, ...]

account-changes = [
    address: B_20,
    storage-changes,
    storage-reads,
    balance-changes,
    nonce-changes,
    code-changes,
]

storage-changes = [slot-changes₁, slot-changes₂, ...]
slot-changes = [slot: P, [storage-change₁, storage-change₂, ...]]
storage-change = [block-access-index: P, value: P]

storage-reads = [slot₁: P, slot₂: P, ...]

balance-changes = [balance-change₁, balance-change₂, ...]
balance-change = [block-access-index: P, balance: P]

nonce-changes = [nonce-change₁, nonce-change₂, ...]
nonce-change = [block-access-index: P, nonce: P]

code-changes = [code-change₁, code-change₂, ...]
code-change = [block-access-index: P, code: B]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage-changes&lt;/code&gt; MUST be sorted by slot ascending. Changes within each slot MUST be sorted by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block-access-index&lt;/code&gt; ascending. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage-reads&lt;/code&gt; MUST be sorted by slot ascending.&lt;/p&gt;

&lt;p&gt;Where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block-access-index&lt;/code&gt; indicates when the change occurred:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; for pre-execution system contract calls&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1...n&lt;/code&gt; for transactions (in block order)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n+1&lt;/code&gt; for post-execution system contract calls and withdrawals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; for complete BAL generation rules and inclusion semantics.&lt;/p&gt;

&lt;h3 id=&quot;new-protocol-messages&quot;&gt;New Protocol Messages&lt;/h3&gt;

&lt;h4 id=&quot;getblockaccesslists-0x12&quot;&gt;GetBlockAccessLists (0x12)&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[request-id: P, [blockhash₁: B_32, blockhash₂: B_32, ...]]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Request BALs for the given block hashes. The number of BALs that can be requested in a single message is subject to implementation-defined limits.&lt;/p&gt;

&lt;p&gt;BALs are only available for blocks after &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; activation and within the retention period defined therein. Requests for unavailable BALs return empty entries.&lt;/p&gt;

&lt;h4 id=&quot;blockaccesslists-0x13&quot;&gt;BlockAccessLists (0x13)&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[request-id: P, [block-access-list₁, block-access-list₂, ...]]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Response to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetBlockAccessLists&lt;/code&gt;. Each element corresponds to a block hash from the request, in order. The RLP empty string (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x80&lt;/code&gt;) is returned for blocks where the BAL is unavailable.&lt;/p&gt;

&lt;p&gt;The recommended soft limit for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockAccessLists&lt;/code&gt; responses is 2 MiB.&lt;/p&gt;

&lt;h3 id=&quot;validation&quot;&gt;Validation&lt;/h3&gt;

&lt;p&gt;When a BAL is received, clients MUST validate it by computing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(rlp.encode(bal))&lt;/code&gt; and comparing against the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block-access-list-hash&lt;/code&gt; in the corresponding block header.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;separate-messages-vs-block-body-extension&quot;&gt;Separate Messages vs. Block Body Extension&lt;/h3&gt;

&lt;p&gt;BALs are transmitted via dedicated messages rather than extending block bodies because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Size&lt;/strong&gt;: BALs average ~70 KiB, significantly increasing block propagation overhead if bundled.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Optional retrieval&lt;/strong&gt;: Not all sync strategies require BALs. Snap sync can reconstruct state without them.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Retention policy&lt;/strong&gt;: BALs may be pruned per &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;, while block bodies are retained longer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;message-ids&quot;&gt;Message IDs&lt;/h3&gt;

&lt;p&gt;Message IDs 0x12 and 0x13 follow sequentially from the existing eth/69 messages (BlockRangeUpdate is 0x11).&lt;/p&gt;

&lt;h3 id=&quot;response-size-limit&quot;&gt;Response Size Limit&lt;/h3&gt;

&lt;p&gt;The 2 MiB soft limit is consistent with other eth protocol responses (blocks, receipts, headers) and accommodates multiple BALs per response. Responses containing a single BAL that exceeds 2 MiB are still valid, as the soft limit governs when to stop appending additional items, not the maximum size of an individual item.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP changes the eth protocol and requires rolling out a new version, eth/71. Supporting multiple protocol versions is standard practice. Rolling out eth/71 does not break older clients, as they can continue using eth/69 or eth/70.&lt;/p&gt;

&lt;p&gt;This EIP requires the Amsterdam hard fork for the header field extension. The new messages are only meaningful for post-Amsterdam blocks.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;validation-cost&quot;&gt;Validation Cost&lt;/h3&gt;

&lt;p&gt;BAL validation requires computing a keccak256 hash of the RLP-encoded list. For typical BALs (~70 KiB), this is negligible. For worst-case BALs at high gas limits, validation remains bounded by the block gas limit.&lt;/p&gt;

&lt;h3 id=&quot;amplification&quot;&gt;Amplification&lt;/h3&gt;

&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetBlockAccessLists&lt;/code&gt; request can trigger responses larger than the request. Implementations SHOULD apply rate limiting and respect the soft response size limit to prevent amplification attacks.&lt;/p&gt;

&lt;h3 id=&quot;unavailable-data&quot;&gt;Unavailable Data&lt;/h3&gt;

&lt;p&gt;Clients MUST handle empty responses gracefully. A peer returning empty entries for available blocks may be misbehaving but could also have pruned the data legitimately.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Thu, 12 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8159</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8159</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>snap/2 - BAL-Based State Healing</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8189 - snap/2 - BAL-Based State Healing&lt;/strong&gt; is in Last Call status. It is authored by Toni Wahrstätter (@nerolation), Gary Rong (@rjl493456442) and was originally created 2026-03-06. It is in the Networking category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8189-snap-2-bal-based-state-healing/27953&quot;&gt;https://ethereum-magicians.org/t/eip-8189-snap-2-bal-based-state-healing/27953&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP upgrades the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snap&lt;/code&gt; protocol from version 1 to version 2, removing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetTrieNodes&lt;/code&gt; (0x06) / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TrieNodes&lt;/code&gt; (0x07) and adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetBlockAccessLists&lt;/code&gt; (0x08) / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockAccessLists&lt;/code&gt; (0x09) to enable BAL-based state healing during snap sync.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; introduces block-level access lists (BALs) that capture all state changes per block, committed to block headers via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block-access-list-hash&lt;/code&gt;. With BALs available, the snap sync healing phase — which iteratively fetches individual Merkle trie nodes via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetTrieNodes&lt;/code&gt; to resolve state inconsistencies — can be replaced entirely.&lt;/p&gt;

&lt;p&gt;Instead of discovering and fetching trie nodes across many round trips, a syncing node downloads BALs for the blocks that advanced during sync and applies state diffs sequentially. Each BAL is verified against its header commitment. The set of blocks to catch up is known upfront, eliminating iterative discovery.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;h3 id=&quot;protocol-version&quot;&gt;Protocol Version&lt;/h3&gt;

&lt;p&gt;The protocol version is incremented from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snap/1&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snap/2&lt;/code&gt;. Peers negotiate the version during the RLPx capability handshake.&lt;/p&gt;

&lt;h3 id=&quot;removed-messages&quot;&gt;Removed Messages&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Message&lt;/th&gt;
      &lt;th&gt;ID&lt;/th&gt;
      &lt;th&gt;Reason&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetTrieNodes&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;0x06&lt;/td&gt;
      &lt;td&gt;Replaced by BAL-based healing&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TrieNodes&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;0x07&lt;/td&gt;
      &lt;td&gt;Replaced by BAL-based healing&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;new-messages&quot;&gt;New Messages&lt;/h3&gt;

&lt;h4 id=&quot;getblockaccesslists-0x08&quot;&gt;GetBlockAccessLists (0x08)&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[request-id: P, [blockhash₁: B_32, blockhash₂: B_32, ...], bytes: P]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Request BALs for the given block hashes. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; is the maximum cumulative size of the BAL data the client is willing to receive in a single response. The number of hashes per request is subject to implementation-defined limits.&lt;/p&gt;

&lt;p&gt;BALs are only available for blocks after &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; activation and within the retention period defined therein.&lt;/p&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Nodes &lt;strong&gt;must&lt;/strong&gt; always respond to the query.&lt;/li&gt;
  &lt;li&gt;If the node does not have the BAL for a requested block hash, it &lt;strong&gt;must&lt;/strong&gt; return the RLP empty string (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x80&lt;/code&gt;) at that position.&lt;/li&gt;
  &lt;li&gt;The responding node is allowed to return &lt;strong&gt;fewer&lt;/strong&gt; entries than requested (serving the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; soft limit or Quality of Service (QoS) limits), truncating from the tail. Returned entries &lt;strong&gt;must&lt;/strong&gt; preserve request order.&lt;/li&gt;
  &lt;li&gt;Nodes &lt;strong&gt;should&lt;/strong&gt; retain BALs for orphaned (non-canonical) blocks within the retention period defined in &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;. Since requests are keyed by block hash, orphaned BALs can be served the same way as canonical ones. Retaining them enables syncing nodes to recover from reorgs past the pivot block without restarting sync.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;blockaccesslists-0x09&quot;&gt;BlockAccessLists (0x09)&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[request-id: P, [block-access-list₁, block-access-list₂, ...]]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Response to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetBlockAccessLists&lt;/code&gt;. Each element corresponds positionally to a block hash from the request. The RLP empty string (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x80&lt;/code&gt;) is returned for blocks where the BAL is unavailable.&lt;/p&gt;

&lt;p&gt;The responding node &lt;strong&gt;should&lt;/strong&gt; respect the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; limit from the request. In the absence of a specific limit, the recommended soft limit for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockAccessLists&lt;/code&gt; responses is 2 MiB.&lt;/p&gt;

&lt;h3 id=&quot;unchanged-messages&quot;&gt;Unchanged Messages&lt;/h3&gt;

&lt;p&gt;Messages 0x00–0x05 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetAccountRange&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AccountRange&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetStorageRanges&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StorageRanges&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetByteCodes&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ByteCodes&lt;/code&gt;) are unchanged from snap/1.&lt;/p&gt;

&lt;h3 id=&quot;validation&quot;&gt;Validation&lt;/h3&gt;

&lt;p&gt;Received BALs &lt;strong&gt;must&lt;/strong&gt; be validated by computing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(rlp.encode(bal))&lt;/code&gt; and comparing against the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block-access-list-hash&lt;/code&gt; in the corresponding block header. See &lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt; for the BAL encoding format.&lt;/p&gt;

&lt;h3 id=&quot;synchronization-algorithm&quot;&gt;Synchronization Algorithm&lt;/h3&gt;

&lt;p&gt;snap/2 replaces trie healing with BAL-based catch-up:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Download headers and identify the chain head.&lt;/li&gt;
  &lt;li&gt;Pick a pivot block P sufficiently behind the chain head (e.g., HEAD-64) to reduce the likelihood of P being reorged while remaining recent enough that serving peers still hold its state in memory.&lt;/li&gt;
  &lt;li&gt;Bulk download state at P via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetAccountRange&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetStorageRanges&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetByteCodes&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;If P becomes stale during bulk download (step 3) — i.e., serving peers no longer hold state at P — the syncing node fetches BALs for blocks P+1 through P’ via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetBlockAccessLists&lt;/code&gt; (where P’ is the new pivot), applies the diffs locally, and continues bulk download at P’.&lt;/li&gt;
  &lt;li&gt;While state is being downloaded, the chain advances and the pivot switches from P to a new block P+K (typically K is 64). Because serving peers may no longer retain the state at P once the pivot advances, the syncing node fetches BALs for blocks P+1 through P+K via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetBlockAccessLists&lt;/code&gt;, applies the state diffs locally, and immediately uses P+K as the new sync target. Each BAL is verified against its header hash before application.&lt;/li&gt;
  &lt;li&gt;If the pivot advances further during step 5, repeat for the newly produced blocks.&lt;/li&gt;
  &lt;li&gt;Recompute and verify the state root against the latest header.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the chain reorgs past the pivot block P, let W be the common ancestor of the old and new canonical chains. The syncing node collects BALs for blocks W+1 through P on the old fork, identifies state entries mutated on the old fork but not on the new fork, deletes those entries locally, and re-fetches them via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetAccountRange&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetStorageRanges&lt;/code&gt;. It then applies BALs from W+1 forward on the new canonical chain and continues sync with a new pivot. If the required orphaned BALs are unavailable, the node must discard state and restart sync.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;separate-protocol-vs-eth71&quot;&gt;Separate Protocol vs. eth/71&lt;/h3&gt;

&lt;p&gt;This follows the established snap design philosophy. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetByteCodes&lt;/code&gt; was duplicated from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snap&lt;/code&gt; for the same reason:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;This functionality was duplicated into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snap&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth/65&lt;/code&gt; to permit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth&lt;/code&gt; long term to become a chain maintenance protocol only and move synchronization primitives out into satellite protocols only.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Synchronization primitives belong in satellite protocols. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snap&lt;/code&gt; is optional and independently versioned; duplicating BAL exchange here avoids coupling sync functionality to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;removing-gettrienodes&quot;&gt;Removing GetTrieNodes&lt;/h3&gt;

&lt;p&gt;BAL-based healing makes trie node fetching for state reconciliation unnecessary. Removing these messages avoids maintaining two healing mechanisms.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP requires rolling out a new protocol version, snap/2. Older clients continue using snap/1. snap/2 is only meaningful for post-Amsterdam blocks, since the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block-access-list-hash&lt;/code&gt; header field (&lt;a href=&quot;/EIPS/eip-7928&quot;&gt;EIP-7928&lt;/a&gt;) is absent for earlier blocks.&lt;/p&gt;

&lt;p&gt;For a node synchronizing data, if both snap/1 and snap/2 are supported, it should use either snap/1 or snap/2 for state sync; running both simultaneously is not recommended. Once the synchronization phase is complete, the node can serve requests for both protocols.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;amplification&quot;&gt;Amplification&lt;/h3&gt;

&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetBlockAccessLists&lt;/code&gt; request can trigger responses significantly larger than the request. Implementations &lt;strong&gt;should&lt;/strong&gt; apply rate limiting and respect the 2 MiB soft response limit.&lt;/p&gt;

&lt;h3 id=&quot;unavailable-data&quot;&gt;Unavailable Data&lt;/h3&gt;

&lt;p&gt;Peers returning empty entries for available blocks may be misbehaving or may have pruned data legitimately. Implementations should track peer reliability and deprioritize unreliable peers.&lt;/p&gt;

&lt;h3 id=&quot;application-order&quot;&gt;Application Order&lt;/h3&gt;

&lt;p&gt;BALs &lt;strong&gt;must&lt;/strong&gt; be applied in strict block order with each BAL hash verified before application. Incorrect ordering or wrong-fork BALs produce an invalid state root, detected during the final state root verification.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 06 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8189</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8189</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Remove SELFDESTRUCT Burn</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8246 - Remove SELFDESTRUCT Burn&lt;/strong&gt; is in Last Call status. It is authored by Paweł Bylica (@chfast) and was originally created 2026-05-01. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8246-remove-selfdestruct-burn/28416&quot;&gt;https://ethereum-magicians.org/t/eip-8246-remove-selfdestruct-burn/28416&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP removes the remaining cases where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; burns ETH. Accounts marked for selfdestruction still have their code, storage, and nonce cleared at transaction finalization, but any remaining balance is preserved.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;The remaining burn behavior of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; is almost completely unused, but it still forces special-case handling in EVM implementations, specifications, and tests.&lt;/p&gt;

&lt;p&gt;After &lt;a href=&quot;/EIPS/eip-6780&quot;&gt;EIP-6780&lt;/a&gt;, ETH can still be burned only when a contract created in the same transaction executes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;, either with itself as beneficiary or in a case where the contract receives additional ETH (via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; or via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;, potentially multiple times) later in the same transaction.
A full replay of Ethereum mainnet from genesis to approximately block 25M found only 2 post-Cancun burns through this path and 0 cases of balance being burned during transaction finalization. By comparison, pre-Cancun history contained 54 self-burns in total. This indicates that the remaining burn behavior is rarer than the burn behavior already removed by EIP-6780, so the complete removal proposed here should affect fewer transactions than the partial removal already introduced there.&lt;/p&gt;

&lt;p&gt;Removing the final burn cases simplifies &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; semantics and avoids preserving an exotic special case that is barely used in practice.&lt;/p&gt;

&lt;p&gt;As a consequence, this also removes the last EVM mechanism by which ETH can leave total supply.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The behavior of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; changes as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; is executed in the same transaction as the contract was created,
and if the beneficiary address is the executing account address,
the balance of this account remains unchanged.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;During transaction finalization,
all accounts marked for selfdestruction,
instead of being deleted,
are modified as follows:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;nonce is reset to 0,&lt;/li&gt;
      &lt;li&gt;balance is unchanged,&lt;/li&gt;
      &lt;li&gt;code is cleared,&lt;/li&gt;
      &lt;li&gt;all storage is cleared.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: All other behavior of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; is unchanged.&lt;/p&gt;

&lt;p&gt;Note: If the resulting balance is 0, the account is &lt;em&gt;empty&lt;/em&gt; and is deleted from the state by &lt;a href=&quot;/EIPS/eip-161&quot;&gt;EIP-161&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;p&gt;This change removes burn behavior at its source instead of adding dedicated handling for it elsewhere.&lt;/p&gt;

&lt;p&gt;The chosen design preserves the state-clearing effect of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; for contracts created in the same transaction. The account may still survive in the state, but only as a balance-only account. This removes the special case where ETH disappears from the state while keeping the account non-executable after transaction finalization.&lt;/p&gt;

&lt;p&gt;Resetting the nonce to 0 ensures that a future &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; at the same address is not blocked by a preserved balance-only account.&lt;/p&gt;

&lt;p&gt;An alternative would be to preserve the whole account, including nonce, code, and storage. That would work as a complete &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; disarming and would remove the burn as well, but it would be a larger semantic change than necessary. This EIP removes only the burn behavior.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP requires a hard fork, since it modifies consensus rules.&lt;/p&gt;

&lt;p&gt;Previously it was possible to burn ETH by executing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; in a contract created in the same transaction, either by targeting the executing contract as beneficiary or by sending ETH to the contract after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; and before transaction finalization. After this EIP, ETH will not be burned in either case.&lt;/p&gt;

&lt;p&gt;Previously such contracts were always deleted at transaction finalization. After this EIP, a contract with zero final balance is still deleted, but a contract with nonzero final balance remains in the state as a balance-only account with empty code, empty storage, and nonce 0.&lt;/p&gt;

&lt;p&gt;For the balance-only accounts created this way, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; still may recreate a contract at the same address in a follow-up transaction. Such a usage pattern remains operational.&lt;/p&gt;

&lt;p&gt;For contracts not created in the same transaction in which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; is executed, the behavior is unchanged from &lt;a href=&quot;/EIPS/eip-6780&quot;&gt;EIP-6780&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unlike Mainnet, some L2 chains use the burn feature of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; regularly and will require a separate migration plan.&lt;/p&gt;

&lt;p&gt;In the OP Stack, ETH withdrawn to L1 accumulates in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L2ToL1MessagePasser&lt;/code&gt; predeploy at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4200000000000000000000000000000000000016&lt;/code&gt;. It provides a permissionless &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;burn()&lt;/code&gt; function which destroys that balance by creating a contract whose constructor executes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; with itself as the beneficiary, so the L2 ETH supply does not inflate. Chains derived from that codebase inherit the dependency unless they modify the predeploy, including those not commonly identified as Optimism-based. Such contracts are deployed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE&lt;/code&gt;, so the balance-only accounts they leave behind cannot be recreated by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; pattern described above.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;h3 id=&quot;unmodified-behavior&quot;&gt;Unmodified behavior&lt;/h3&gt;

&lt;p&gt;General test coverage of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; instruction is expected to be excellent already because this instruction has been modified multiple times in the past. Updating existing test cases to align with this EIP should give us good coverage of all &lt;strong&gt;unmodified&lt;/strong&gt; features of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;modified-behavior&quot;&gt;Modified behavior&lt;/h3&gt;

&lt;p&gt;Each of the following test cases should be executed (where physically meaningful) across the combinations of these factors:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;level: top-level transaction, internal call,&lt;/li&gt;
  &lt;li&gt;call type: CALL (including top-level tx), CREATE (including top-level tx), CREATE2,&lt;/li&gt;
  &lt;li&gt;code state: SELFDESTRUCT executed inside initcode (before deployment) / from deployed code,&lt;/li&gt;
  &lt;li&gt;status: SELFDESTRUCT succeeds, SELFDESTRUCT fails due to OOG,&lt;/li&gt;
  &lt;li&gt;revert: effects of SELFDESTRUCT are committed to the post-state, effects of SELFDESTRUCT are reverted (only for wrapped internal calls),&lt;/li&gt;
  &lt;li&gt;balance: balance of the selfdestructing account at the SELFDESTRUCT instruction is zero / non-zero.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;instruction-level&quot;&gt;Instruction level&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-self.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-self, followed by selfdestruct-to-self.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-self, followed by selfdestruct-to-other.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-other, followed by selfdestruct-to-self.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;transaction-finalization&quot;&gt;Transaction finalization&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-other, followed by a CALL with value to the selfdestructed account.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-other, followed by multiple CALLs with value to the selfdestructed account.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-other, followed by a CALL with value to the selfdestructed account, followed by selfdestruct-to-other.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-other, followed by a CALL with value to the selfdestructed account, followed by selfdestruct-to-self.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-self, followed by a CALL with value to the selfdestructed account.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-self, followed by multiple CALLs with value to the selfdestructed account.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-self, followed by a CALL with value to the selfdestructed account, followed by selfdestruct-to-other.&lt;/li&gt;
  &lt;li&gt;Same-transaction selfdestruct-to-self, followed by a CALL with value to the selfdestructed account, followed by selfdestruct-to-self.&lt;/li&gt;
  &lt;li&gt;Create new account, new account creates other accounts to bump its nonce, new account selfdestruct-to-self.&lt;/li&gt;
  &lt;li&gt;Create new account, new account creates other accounts to bump its nonce, new account selfdestruct-to-other.&lt;/li&gt;
  &lt;li&gt;Create new account, new account adds new storage, new account selfdestruct-to-self.&lt;/li&gt;
  &lt;li&gt;Create new account, new account adds new storage, new account selfdestruct-to-other.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;multi-transaction&quot;&gt;Multi-transaction&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Tx-1: CREATE2 new account with non-zero balance, new account selfdestruct-to-self. Tx-2: Repeats Tx-1.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELFDESTRUCT&lt;/code&gt; behavior modification has a combinatorial effect on a vast number of test scenarios involving multi-call/create contract interactions. This EIP requires significant testing effort. However, many existing test cases for EIP-6780 can be adapted to the new behavior.&lt;/li&gt;
  &lt;li&gt;When a use case relies on the ETH burn happening, the transaction will create dust-like accounts with potentially locked non-zero balance. However, the new account creation gas cost is paid by the transaction, so dust accounts are not a free DoS vector. Only 2 such events have been recorded on Mainnet (Cancun–25M) so far.&lt;/li&gt;
  &lt;li&gt;Preserving the balance leaves a funded account whose nonce, code and storage are cleared, which makes the address a valid &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; target again (a non-zero balance alone never triggers a creation collision, per &lt;a href=&quot;/EIPS/eip-684&quot;&gt;EIP-684&lt;/a&gt;). The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(sender, salt, initcode)&lt;/code&gt; of a deployment is public data, so when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender&lt;/code&gt; is a permissionless factory anyone can redeploy the account and potentially take the preserved balance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8246</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8246</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Gas Limit Schedule</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8261 - Gas Limit Schedule&lt;/strong&gt; is in Last Call status. It is authored by Barnabas Busa (@barnabasbusa) and was originally created 2026-05-11. It is in the  category of type Informational. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8261-gas-limit-schedule/28494&quot;&gt;https://ethereum-magicians.org/t/eip-8261-gas-limit-schedule/28494&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP recommends that, starting with Gloas (&lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt;), consensus layer clients source their gas limit preference from an optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_LIMIT_SCHEDULE&lt;/code&gt; field in the consensus layer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.yaml&lt;/code&gt; instead of hardcoded, release-scoped defaults. Each entry activates at the start of its specified epoch and provides a value that plays two roles: it is the &lt;strong&gt;default&lt;/strong&gt; gas limit that validator clients target in the absence of operator configuration, and the &lt;strong&gt;recommended maximum&lt;/strong&gt;. The schedule is ignored before Gloas, preserving existing gas limit behavior. Operators remain free to configure any value; clients should warn when a configured preference exceeds the active scheduled value, but honor it because the maximum is a recommendation, not a rule. The schedule lives only on the consensus layer because post-Gloas the validator’s preference flows through validator registrations and the builder pipeline, with no execution layer configuration involved. No consensus rules are changed: the &lt;a href=&quot;/EIPS/eip-1559&quot;&gt;EIP-1559&lt;/a&gt; ±1/1024 elasticity rule remains the only gas-limit validity rule, and blocks above or below the scheduled value remain valid.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Today the block gas limit is set by each block proposer, driven by validator client “preferred gas limit” settings, client default configurations, and builder bids, with the ±1/1024 elasticity rule from &lt;a href=&quot;/EIPS/eip-1559&quot;&gt;EIP-1559&lt;/a&gt; moving the realized limit block by block.&lt;/p&gt;

&lt;p&gt;The pain point this EIP addresses is that gas limit defaults are &lt;strong&gt;release-scoped&lt;/strong&gt; rather than &lt;strong&gt;epoch-based&lt;/strong&gt;: a new default activates whenever an operator happens to update their node, not at a network-coordinated epoch. This creates a concrete coordination problem for large increases. Suppose clients want to raise the default from 60M toward a substantially higher value at a future epoch:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If clients ship the new default in releases ahead of the activation epoch, every node updated early starts voting the gas limit up &lt;em&gt;immediately&lt;/em&gt;, before the network has agreed the new value is safe to reach.&lt;/li&gt;
  &lt;li&gt;The alternative, shipping the new default in a back-to-back release immediately after the intended activation epoch and asking all operators to update quickly, is operationally inconvenient and slow to take effect.&lt;/li&gt;
  &lt;li&gt;One-off override flags for each planned increase push the coordination burden onto every individual operator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also no single place where “the gas limit the network should run at” is written down: moving the network today requires either every client team shipping a new hardcoded default, or a large share of operators updating flags, coordinated socially over months. &lt;a href=&quot;/EIPS/eip-7935&quot;&gt;EIP-7935&lt;/a&gt; demonstrated that coordinating a default gas limit recommendation at a known epoch works; this EIP generalizes that approach into a reusable, machine-readable schedule, mirroring the epoch-based &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLOB_SCHEDULE&lt;/code&gt; configuration format from &lt;a href=&quot;/EIPS/eip-7892&quot;&gt;EIP-7892&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With Gloas (&lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt;), the consensus layer becomes the natural single home for this schedule: the gas limit a block is built to originates from the validator side of the builder flow, so a CL configuration entry can drive the network’s gas limit end to end without any execution layer configuration.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This EIP changes no consensus rules. The &lt;a href=&quot;/EIPS/eip-1559&quot;&gt;EIP-1559&lt;/a&gt; gas limit validity rules (±1/1024 elasticity, 5000 minimum) are unchanged, and a block whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_limit&lt;/code&gt; differs from the scheduled value in either direction remains valid. Everything below is recommended client and tooling behavior.&lt;/p&gt;

&lt;h3 id=&quot;gas-limit-schedule&quot;&gt;Gas limit schedule&lt;/h3&gt;

&lt;p&gt;The consensus layer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.yaml&lt;/code&gt; MAY be extended with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_LIMIT_SCHEDULE&lt;/code&gt; field, mirroring the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLOB_SCHEDULE&lt;/code&gt; mechanism in &lt;a href=&quot;/EIPS/eip-7892&quot;&gt;EIP-7892&lt;/a&gt;. Entries represent recommended gas limit changes that take effect at the start of the listed epoch:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;GAS_LIMIT_SCHEDULE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;EPOCH&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;500000&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Gloas activation epoch&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GAS_LIMIT&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;60000000&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;EPOCH&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;520000&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# A later scheduled increase&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GAS_LIMIT&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;75000000&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;EPOCH&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;540000&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Another scheduled increase&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GAS_LIMIT&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;90000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EPOCH&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_LIMIT&lt;/code&gt; are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt; values; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_LIMIT&lt;/code&gt; matches the type of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecutionPayload.gas_limit&lt;/code&gt; in the consensus specifications.&lt;/p&gt;

&lt;p&gt;The field is OPTIONAL: CL clients MAY add support for it, and clients that do not recognize it ignore it, per the existing convention for unknown configuration keys. Supporting clients MUST ignore the schedule for duties before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GLOAS_FORK_EPOCH&lt;/code&gt;. A client that is not using the parameter because the duty is pre-Gloas, the field is absent, or no schedule entry is active simply keeps its existing gas limit behavior.&lt;/p&gt;

&lt;p&gt;Each entry independently schedules a recommended gas limit change at its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EPOCH&lt;/code&gt;. An entry MAY align with a protocol upgrade, but the schedule itself does not create or require a fork.&lt;/p&gt;

&lt;p&gt;Define:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_scheduled_gas_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GLOAS_FORK_EPOCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;active_entries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GAS_LIMIT_SCHEDULE&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EPOCH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;active_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Latest schedule entry whose EPOCH &amp;lt;= epoch
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EPOCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GAS_LIMIT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;recommended-client-behavior&quot;&gt;Recommended client behavior&lt;/h3&gt;

&lt;p&gt;For CL clients that support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GAS_LIMIT_SCHEDULE&lt;/code&gt;, an active scheduled value serves as both the default gas limit and the recommended maximum:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Default.&lt;/strong&gt; When no operator preference is supplied and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_scheduled_gas_limit(epoch)&lt;/code&gt; returns a value, the client SHOULD use it as the gas limit preference, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;epoch&lt;/code&gt; is the epoch of the slot the registration or proposal applies to. Before Gloas or when no entry is active, the client SHOULD retain its existing default behavior. Clients SHOULD NOT introduce a separate release-scoped default for epochs covered by an active schedule entry.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Recommended maximum.&lt;/strong&gt; If an operator-supplied preference exceeds the active scheduled value, the client SHOULD honor it, since this EIP introduces no enforcement, but SHOULD log a clear warning, e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configured gas limit 100000000 exceeds the recommended maximum of 90000000 at epoch 540000&lt;/code&gt;. Exceeding the recommendation is thereby a deliberate, visible operator decision rather than a silent one.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Operator preferences are always honored.&lt;/strong&gt; Values below the scheduled value work unchanged, as today.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Builders and relays.&lt;/strong&gt; When a schedule entry is active, builders SHOULD produce, and relays SHOULD prefer, bids whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gas_limit&lt;/code&gt; does not exceed the scheduled value for the bid’s slot.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;epoch-based-switching&quot;&gt;Epoch-based switching&lt;/h4&gt;

&lt;p&gt;The schedule only delivers its benefit if the effective default changes exactly at the configured epoch boundary, which requires new client logic: today, gas limit defaults are read once (at startup, or when a validator registration is created) and held constant. Under this EIP, the scheduled value SHOULD be looked up per duty against the epoch of the slot being proposed or registered for, never against wall-clock time or a value cached at startup. A running node then switches its preference at the first slot of the configured epoch with no restart, follow-up release, or operator action. Since validator registrations are re-issued periodically, registrations naturally roll over to a new scheduled value as duties cross the activation epoch.&lt;/p&gt;

&lt;p&gt;Because the schedule is keyed by epoch, a release shipped months before an entry activates keeps using the current value until that epoch, then switches automatically. This makes it safe to ship large future increases well ahead of time: early updaters do not begin voting toward the new value before its configured activation epoch.&lt;/p&gt;

&lt;h4 id=&quot;the-consensus-layer-drives-the-gas-limit&quot;&gt;The consensus layer drives the gas limit&lt;/h4&gt;

&lt;p&gt;Starting with Gloas (&lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt;), the gas limit a block is built to originates on the consensus layer side of the builder flow — the validator’s preference, expressed through validator registrations and the payload bid path — rather than from execution layer configuration. The schedule therefore lives only in the CL &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.yaml&lt;/code&gt;; no execution layer chain-configuration counterpart is needed, and EL gas limit flags retain their existing pre-Gloas and local-tooling meaning. This EIP does not change gas limit selection before Gloas.&lt;/p&gt;

&lt;p&gt;Illustrative preference selection:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;effective_gas_limit_preference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;operator_preference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;existing_default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;scheduled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_scheduled_gas_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scheduled&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator_preference&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator_preference&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;existing_default&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator_preference&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scheduled&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator_preference&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scheduled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;configured gas limit &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;operator_preference&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; exceeds the recommended &quot;&lt;/span&gt;
            &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;maximum of &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scheduled&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; at epoch &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator_preference&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The realized network gas limit continues to move under the &lt;a href=&quot;/EIPS/eip-1559&quot;&gt;EIP-1559&lt;/a&gt; ±1/1024 rule, so a scheduled increase plays out as a gradual, bounded ramp starting at the activation epoch rather than an instant step.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;why-epoch-based-defaults-instead-of-release-scoped-defaults&quot;&gt;Why epoch-based defaults instead of release-scoped defaults?&lt;/h3&gt;

&lt;p&gt;Keying the default on the duty’s epoch rather than the release version decouples &lt;em&gt;shipping&lt;/em&gt; a new gas limit from &lt;em&gt;activating&lt;/em&gt; it. This directly resolves the large-increase dilemma described in the Motivation: clients can ship the schedule entry for a big raise arbitrarily early, and no node will begin voting toward it until the configured epoch. An entry can align with a hard fork when desired, but the mechanism itself is only an epoch-based client configuration.&lt;/p&gt;

&lt;h3 id=&quot;why-one-value-for-both-the-default-and-the-recommended-maximum&quot;&gt;Why one value for both the default and the recommended maximum?&lt;/h3&gt;

&lt;p&gt;The number the community coordinates on for an epoch is the number the network runs at and the number operators are asked not to exceed. A single dial means there is no second parameter to negotiate or get out of sync, and no untested operating region between a default and a higher ceiling. Operators who want to run below it can; running above it is possible (nothing in consensus prevents it) but happens against a clear warning, which is a much stronger signal than today’s silently configurable free-for-all.&lt;/p&gt;

&lt;h3 id=&quot;why-does-the-schedule-live-only-on-the-consensus-layer&quot;&gt;Why does the schedule live only on the consensus layer?&lt;/h3&gt;

&lt;p&gt;Post-Gloas, the CL is authoritative for the gas limit in practice: the validator preference drives registrations, builder bids, and payload construction. A parallel execution layer schedule would be redundant configuration that could only ever agree with or diverge from the CL’s — and divergence is a new failure mode with no benefit. One schedule, in the layer that actually drives the value, is the minimal design. EL clients require no changes at all under this EIP.&lt;/p&gt;

&lt;h3 id=&quot;why-informational-rather-than-a-consensus-rule&quot;&gt;Why informational rather than a consensus rule?&lt;/h3&gt;

&lt;p&gt;An earlier draft of this EIP made the scheduled value a consensus-enforced maximum (and, before that, an exact-match requirement). This version is deliberately advisory:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Adoptability.&lt;/strong&gt; A recommendation requires no fork, no engine API changes, and no coordination risk. The configuration field is optional, so CL teams can adopt it independently and incrementally, and entries can activate at any coordinated post-Gloas epoch.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Validator sovereignty is preserved.&lt;/strong&gt; Gas limit choice remains, in the limit, with proposers — this EIP changes the &lt;em&gt;defaults and social convention&lt;/em&gt; around that choice, not the protocol.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;It solves the actual coordination problem.&lt;/strong&gt; The premature-voting and back-to-back-release problems are default-management problems, and defaults are client behavior. Consensus enforcement addresses a different (drift-above-tested-envelope) risk, and can be pursued later as a separate Core EIP layered on the same schedule if the community wants it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;why-warn-rather-than-clamp-out-of-range-preferences&quot;&gt;Why warn rather than clamp out-of-range preferences?&lt;/h3&gt;

&lt;p&gt;Clamping a preference down to the scheduled value would be enforcement — just relocated from consensus into the client. Without a consensus rule behind it, that would be dishonest in both directions: it implies a network ceiling that does not actually exist (any proposer running a non-conforming client could still exceed it), and it silently overrides an explicit operator decision that produces perfectly valid blocks. It would also fragment behavior across clients, since only those that adopt the optional schedule would clamp. A prominent warning keeps the mechanism honest: the schedule shapes defaults, and exceeding the recommended maximum remains possible but becomes a deliberate, visible act instead of a silent misconfiguration.&lt;/p&gt;

&lt;h3 id=&quot;relationship-to-eip-7935&quot;&gt;Relationship to EIP-7935&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7935&quot;&gt;EIP-7935&lt;/a&gt; recommended a single default (60M) tied to Fusaka’s activation. This EIP generalizes that one-off into a standing, machine-readable epoch schedule so future changes reuse the same mechanism instead of requiring a new EIP and a fresh round of client-default coordination.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;No consensus rules change and no blocks become invalid. Pre-Gloas behavior and existing operator settings remain unchanged. For post-Gloas duties covered by an active schedule entry, unconfigured validators derive their gas limit preference from the schedule instead of a hardcoded constant, and configured values above the scheduled maximum produce a warning but are honored. CL clients that do not adopt the field, and all EL clients, are unaffected. Tooling that reads &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.gas_limit&lt;/code&gt; is unaffected.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The ceiling is advisory.&lt;/strong&gt; Nothing in consensus prevents a proposer from exceeding the scheduled value, so this EIP does not protect against a deliberately non-conforming actor. It does protect against the accidental paths — a default shipped early, a stale setting, an uncoordinated bump — which historically are how unintended gas limit movement happens. The ±1/1024 elasticity rule further rate-limits how fast any actor, conforming or not, can move the realized limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Herding on the schedule.&lt;/strong&gt; If most validators follow the schedule, the network’s gas limit becomes highly predictable, which is the goal. It also means an error in a scheduled value propagates widely; scheduled values should receive the same devnet and worst-case-block testing that gas limit increases receive today (as described in &lt;a href=&quot;/EIPS/eip-7935&quot;&gt;EIP-7935&lt;/a&gt;) before being added to a network’s configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Partial adoption.&lt;/strong&gt; Because the field is optional, clients that do not support it keep their existing defaults, and their operators keep coordinating manually. The mechanism’s coordination benefit is proportional to adoption; a mixed network is no worse than today, since non-supporting clients behave exactly as they do now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Path to enforcement.&lt;/strong&gt; If the community later wants a hard guarantee that the network cannot exceed a tested envelope, a future Standards Track Core EIP can promote this schedule’s value to a consensus-enforced maximum without changing the configuration format.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8261</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8261</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Builder Execution Requests</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8282 - Builder Execution Requests&lt;/strong&gt; is in Last Call status. It is authored by Cayman (@wemeetagain), Nico Flaig &lt;nflaig@protonmail.com&gt;, Felix Lange &lt;fjl@ethereum.org&gt;, Justin Traglia &lt;jtraglia@ethereum.org&gt; and was originally created 2026-05-22. It is in the Core category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/eip-8282-builder-execution-requests/28699&quot;&gt;https://ethereum-magicians.org/t/eip-8282-builder-execution-requests/28699&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP introduces two &lt;a href=&quot;/EIPS/eip-7685&quot;&gt;EIP-7685&lt;/a&gt; request types and corresponding predeploy contracts for &lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt; builders. A builder deposit contract handles initial registration and stake top-ups. A builder exit contract lets a builder’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_address&lt;/code&gt; trigger a full exit. Both contracts follow the request-bus pattern of &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-7251&quot;&gt;EIP-7251&lt;/a&gt;. Builders no longer onboard through the validator deposit flow or exit through the voluntary-exit operation.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt; introduces builders as a separate, staked consensus-layer actor, but reuses validator flows for their lifecycle. A builder is registered by a validator deposit whose withdrawal credential carries the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xB0&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_WITHDRAWAL_PREFIX&lt;/code&gt;, and it exits through a builder branch of the voluntary-exit operation. Dedicated builder request types improve on this in several ways.&lt;/p&gt;

&lt;p&gt;Dedicated types make the actor explicit from the request type alone. The consensus layer no longer routes deposits by inspecting credential prefixes, and the validator and builder registries are keyed independently.&lt;/p&gt;

&lt;p&gt;A builder deposit’s proof-of-possession is verified inline when the deposit is processed, unlike a validator deposit’s, which is deferred to the churn-limited &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending_deposits&lt;/code&gt; queue. Builder deposits carried on the validator deposit request inherit its high per-payload ceiling. A dedicated request type isolates the verification work and caps it at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_DEPOSIT_REQUESTS_PER_BLOCK&lt;/code&gt; per block.&lt;/p&gt;

&lt;p&gt;Under &lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt;, a builder can only exit with a signature from its BLS key, the same hot key that signs its bids. The exit contract instead authorizes exit by the builder’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_address&lt;/code&gt;, as &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt; does for validators.&lt;/p&gt;

&lt;p&gt;Builders that must exist at the fork are unaffected. The &lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt; fork-transition onboarding of builder-credentialed pending deposits is retained, and only post-fork onboarding moves to the new contract.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;constants&quot;&gt;Constants&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
      &lt;th&gt;Comment&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_DEPOSIT_CONTRACT_ADDRESS&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0000bFF46984e3725691FA540a8C7589300D8282&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Predeploy address of the builder deposit contract&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_EXIT_CONTRACT_ADDRESS&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x000064D678505ad48F8cCb093BC65613800E8282&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Predeploy address of the builder exit contract&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_DEPOSIT_REQUEST_TYPE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x03&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;/EIPS/eip-7685&quot;&gt;EIP-7685&lt;/a&gt; request-type byte for builder deposits&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_EXIT_REQUEST_TYPE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x04&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;/EIPS/eip-7685&quot;&gt;EIP-7685&lt;/a&gt; request-type byte for builder exits&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSTEM_ADDRESS&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xfffffffffffffffffffffffffffffffffffffffe&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Address that invokes the end-of-block system call (as in &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt;)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_DEPOSIT_REQUESTS_PER_BLOCK&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;64&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Maximum records the builder deposit contract drains into one block&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TARGET_DEPOSIT_REQUESTS_PER_BLOCK&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Per-block request count above which the fee rises for the deposit contract&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_EXIT_REQUESTS_PER_BLOCK&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;16&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Maximum records the builder exit contract drains into one block&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TARGET_EXIT_REQUESTS_PER_BLOCK&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Per-block request count above which the fee rises for the exit contract&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MIN_REQUEST_FEE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Minimum request fee, in wei&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REQUEST_FEE_UPDATE_FRACTION&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;17&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Controls the fee’s rate of change&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_MIN_DEPOSIT&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1000000000000000000&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Minimum credited stake for a deposit, in wei (1 ETH — the &lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt; builder minimum)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_DEPOSIT_CONTRACT_RUNTIME_CODE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;em&gt;see &lt;a href=&quot;#reference-implementation&quot;&gt;Reference Implementation&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;Runtime bytecode of the builder deposit contract&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_EXIT_CONTRACT_RUNTIME_CODE&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;em&gt;see &lt;a href=&quot;#reference-implementation&quot;&gt;Reference Implementation&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;Runtime bytecode of the builder exit contract&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Final request-type values MUST be unique across all active &lt;a href=&quot;/EIPS/eip-7685&quot;&gt;EIP-7685&lt;/a&gt; request types. Allocation is coordinated in consensus-specs, where the existing types are defined (&lt;a href=&quot;https://github.com/ethereum/consensus-specs/blob/e310d1c0d316e4dcc822164966c5bfa592adae2b/specs/electra/beacon-chain.md&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;electra/beacon-chain.md&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;h3 id=&quot;deployment&quot;&gt;Deployment&lt;/h3&gt;

&lt;p&gt;Both contracts are deployed by a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; factory (&lt;a href=&quot;/EIPS/eip-7997&quot;&gt;EIP-7997&lt;/a&gt;). Each address is determined by the factory, a salt, and the contract’s init code. The salt was mined so that the addresses above result from the current reference bytecode.&lt;/p&gt;

&lt;p&gt;The contracts MUST be deployed before the fork that activates this EIP. If there is no code at either address once the EIP is active, every block from activation onward MUST be invalid.&lt;/p&gt;

&lt;h3 id=&quot;request-queue-and-system-call&quot;&gt;Request queue and system call&lt;/h3&gt;

&lt;p&gt;Both predeploys follow the &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-7251&quot;&gt;EIP-7251&lt;/a&gt; contract design, with minor tweaks, and reuse their storage layout. There is no Solidity-compatible ABI. Each contract dispatches on the caller and on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;calldatasize&lt;/code&gt; alone. Calls that match none of the cases below MUST revert.&lt;/p&gt;

&lt;h4 id=&quot;write-path&quot;&gt;Write path&lt;/h4&gt;

&lt;p&gt;A call from any address other than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSTEM_ADDRESS&lt;/code&gt;, with calldata of exactly the contract’s input size, submits a request. The contract MUST validate the request and the value sent (see below), append one record to its queue, increment the per-block count, and emit the accepted record as an anonymous log.&lt;/p&gt;

&lt;h4 id=&quot;fee-getter&quot;&gt;Fee getter&lt;/h4&gt;

&lt;p&gt;A call from any address other than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSTEM_ADDRESS&lt;/code&gt;, with empty calldata, returns the current fee without modifying state. The contract MUST revert if any value is attached.&lt;/p&gt;

&lt;h4 id=&quot;system-call&quot;&gt;System call&lt;/h4&gt;

&lt;p&gt;At the end of each block, the contract is called by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSTEM_ADDRESS&lt;/code&gt;. If any calldata is included, the queue is permanently disabled via an inhibitor. If no calldata is included, it MUST dequeue up to its per-block maximum of records (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_DEPOSIT_REQUESTS_PER_BLOCK&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_EXIT_REQUESTS_PER_BLOCK&lt;/code&gt;, oldest first), return their concatenation as its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;request_data&lt;/code&gt;, and reset the per-block count. Records beyond the cap remain queued for subsequent blocks.&lt;/p&gt;

&lt;p&gt;The execution layer prepends the contract’s request-type byte and includes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;request_type ++ request_data&lt;/code&gt; in the block requests list, committed via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requests_hash&lt;/code&gt; (&lt;a href=&quot;/EIPS/eip-7685&quot;&gt;EIP-7685&lt;/a&gt;). The system call follows the same rules as in &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt;. It runs with a dedicated gas limit of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;30_000_000&lt;/code&gt; that does not count against the block gas limit. If either contract’s system call fails, the block MUST be invalid.&lt;/p&gt;

&lt;h3 id=&quot;request-fee&quot;&gt;Request fee&lt;/h3&gt;

&lt;p&gt;Each request carries a fee, computed as in &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fee = fake_exponential(MIN_REQUEST_FEE, excess, REQUEST_FEE_UPDATE_FRACTION)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fake_exponential&lt;/code&gt; is the &lt;a href=&quot;/EIPS/eip-1559&quot;&gt;EIP-1559&lt;/a&gt;-style integer approximation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MIN_REQUEST_FEE * e**(excess / REQUEST_FEE_UPDATE_FRACTION)&lt;/code&gt;. The fee rises super-linearly while blocks contain more than the target number of requests and decays back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MIN_REQUEST_FEE&lt;/code&gt; otherwise. It is charged on top of any staked value and is left locked in the contract.&lt;/p&gt;

&lt;p&gt;Both contracts are modified to apply fee increases for each write path, rather than at end-of-block, as in &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;deposit-requests&quot;&gt;Deposit requests&lt;/h3&gt;

&lt;p&gt;A deposit request is submitted by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_DEPOSIT_CONTRACT_ADDRESS&lt;/code&gt; with calldata of exactly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;184&lt;/code&gt; bytes:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Bytes&lt;/th&gt;
      &lt;th&gt;Field&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0:48&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pubkey&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;48-byte BLS public key&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;48:80&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;withdrawal_credentials&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;32-byte commitment (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;version&lt;/code&gt; byte + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_address&lt;/code&gt;)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;80:88&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Big-endian &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;, in gwei&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;88:184&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signature&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;96-byte BLS proof-of-possession&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;A deposit request serves both a builder’s first deposit and subsequent top-ups. The contract MUST reject the request unless &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount * 1 gwei &amp;gt;= BUILDER_MIN_DEPOSIT&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.value &amp;gt;= amount * 1 gwei + fee&lt;/code&gt;. Any value beyond &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount * 1 gwei + fee&lt;/code&gt; is retained by the contract and not credited to the builder.&lt;/p&gt;

&lt;p&gt;On success the contract queues the 184 input bytes. The dequeued record is the input verbatim with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount&lt;/code&gt; converted to little-endian, as in &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt;. The contract does not verify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signature&lt;/code&gt;. It is carried in the record and verified by the consensus layer. Submitters SHOULD verify the proof-of-possession off-chain before broadcasting a first deposit.&lt;/p&gt;

&lt;h3 id=&quot;exit-requests&quot;&gt;Exit requests&lt;/h3&gt;

&lt;p&gt;An exit request is submitted by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_EXIT_CONTRACT_ADDRESS&lt;/code&gt; with calldata of exactly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;48&lt;/code&gt; bytes, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pubkey&lt;/code&gt; of the builder to exit. The contract MUST require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.value &amp;gt;= fee&lt;/code&gt;. No value is staked. On success it queues a record of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source_address (20) ++ pubkey (48)&lt;/code&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source_address&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Authorization is by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source_address&lt;/code&gt;, as in &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt;. The contract records &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; and performs no further check. The consensus layer honors the request only when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source_address&lt;/code&gt; equals the target builder’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_address&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;consensus-layer-processing&quot;&gt;Consensus layer processing&lt;/h3&gt;

&lt;p&gt;The consensus layer decodes each dequeued record into one of two SSZ containers, selected by request type:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BuilderDepositRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pubkey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bytes48&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;withdrawal_credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bytes32&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint64&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Gwei
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bytes96&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BuilderExitRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;source_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bytes20&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pubkey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bytes48&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A type’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;request_data&lt;/code&gt; is the concatenation of the fixed-size SSZ serializations of its records, which is exactly the bytes the system call returns, in the same order. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderDepositRequest&lt;/code&gt; is the &lt;a href=&quot;/EIPS/eip-6110&quot;&gt;EIP-6110&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DepositRequest&lt;/code&gt; without the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;Detailed state-transition behavior is specified in consensus-specs. In summary:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderDepositRequest&lt;/code&gt; for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pubkey&lt;/code&gt; not in the builder registry registers a new builder if its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signature&lt;/code&gt; is a valid proof-of-possession over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(pubkey, withdrawal_credentials, amount)&lt;/code&gt; under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMAIN_BUILDER_DEPOSIT&lt;/code&gt;, a builder-specific signing domain. A record with an invalid signature is ignored and its stake forfeited. Deposits are applied immediately rather than routed through the validator &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending_deposits&lt;/code&gt; queue.&lt;/li&gt;
  &lt;li&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderDepositRequest&lt;/code&gt; for an already-registered &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pubkey&lt;/code&gt; is a top-up. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amount&lt;/code&gt; is credited and the record’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;withdrawal_credentials&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signature&lt;/code&gt; are ignored, as with validator deposits.&lt;/li&gt;
  &lt;li&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuilderExitRequest&lt;/code&gt; initiates a full exit only if its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pubkey&lt;/code&gt; is an active builder, its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source_address&lt;/code&gt; equals that builder’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_address&lt;/code&gt;, and the builder has no pending balance to withdraw. Otherwise the record is dropped rather than re-queued, and the request must be resubmitted.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;changes-to-eip-7732&quot;&gt;Changes to EIP-7732&lt;/h3&gt;

&lt;h4 id=&quot;deposit-routing&quot;&gt;Deposit routing&lt;/h4&gt;

&lt;p&gt;The builder branch of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_deposit_request&lt;/code&gt; is removed, so a deposit to the validator deposit contract is always an ordinary validator deposit. Builders are created and topped up only through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_DEPOSIT_REQUEST_TYPE&lt;/code&gt;. A post-fork deposit to the validator contract with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xB0&lt;/code&gt; credential mints a validator that cannot withdraw its balance, so builder deposits MUST be sent to the builder deposit contract.&lt;/p&gt;

&lt;h4 id=&quot;fork-transition-onboarding&quot;&gt;Fork-transition onboarding&lt;/h4&gt;

&lt;p&gt;The one-time &lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt; onboarding of builder-credentialed pending deposits at the fork is retained, so builders exist from the first slot. This is the only path that onboards builders through the validator deposit contract. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xB0&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_WITHDRAWAL_PREFIX&lt;/code&gt; is deprecated afterward.&lt;/p&gt;

&lt;h4 id=&quot;exit-routing&quot;&gt;Exit routing&lt;/h4&gt;

&lt;p&gt;The builder branch of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_voluntary_exit&lt;/code&gt; is removed, making the voluntary-exit operation validator-only. Builders exit only through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_EXIT_REQUEST_TYPE&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;two-predeploys-two-request-types&quot;&gt;Two predeploys, two request types&lt;/h3&gt;

&lt;p&gt;This mirrors withdrawals (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x01&lt;/code&gt;) and consolidations (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x02&lt;/code&gt;). The execution layer needs no new read semantics, and the consensus layer routes by request type rather than by inspecting credentials.&lt;/p&gt;

&lt;h3 id=&quot;one-request-for-deposits-and-top-ups&quot;&gt;One request for deposits and top-ups&lt;/h3&gt;

&lt;p&gt;This matches the validator deposit contract. The proof-of-possession is checked on a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pubkey&lt;/code&gt;’s first appearance, and later deposits credit stake. A top-up cannot redirect a builder’s withdrawals because its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;withdrawal_credentials&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signature&lt;/code&gt; are ignored.&lt;/p&gt;

&lt;h3 id=&quot;exit-by-execution_address&quot;&gt;Exit by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_address&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;A builder’s BLS key is hot, since it signs bids continuously, so it should not also authorize exits. Routing exit through the cold &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_address&lt;/code&gt; mirrors the &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt; rationale for validator withdrawal credentials and gives builders a single, well-defined exit authorizer.&lt;/p&gt;

&lt;h3 id=&quot;request-fee-1&quot;&gt;Request fee&lt;/h3&gt;

&lt;p&gt;The same demand-responsive fee as &lt;a href=&quot;/EIPS/eip-7002&quot;&gt;EIP-7002&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-7251&quot;&gt;EIP-7251&lt;/a&gt; meters submission, together with the per-block caps and the per-deposit stake.&lt;/p&gt;

&lt;h3 id=&quot;onboarding-at-the-fork&quot;&gt;Onboarding at the fork&lt;/h3&gt;

&lt;p&gt;Some applications depend on builders existing from the first slot of the fork, which post-fork deposits to the new contract cannot provide. The existing &lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt; onboarding path is therefore retained for the initial builder set.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This EIP is additive at the execution layer. It introduces new contracts at previously empty addresses and does not modify the validator deposit contract or the validator request predeploys. At the consensus layer it modifies the &lt;a href=&quot;/EIPS/eip-7732&quot;&gt;EIP-7732&lt;/a&gt; builder lifecycle as described in &lt;a href=&quot;#changes-to-eip-7732&quot;&gt;Changes to EIP-7732&lt;/a&gt;. Builders onboarded at the fork are unaffected.&lt;/p&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;See &lt;a href=&quot;https://github.com/ethereum/sys-asm/tree/3bba94c696bc46beeecef05db6c2df0f18b4b239/src/builder_deposits&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/builder_deposits&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/ethereum/sys-asm/tree/3bba94c696bc46beeecef05db6c2df0f18b4b239/src/builder_exits&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/builder_deposits&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;exit-authorization&quot;&gt;Exit authorization&lt;/h3&gt;

&lt;p&gt;The exit contract records &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source_address&lt;/code&gt; and performs no further check. The request carries no signature, so the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source_address&lt;/code&gt; check during &lt;a href=&quot;#consensus-layer-processing&quot;&gt;consensus layer processing&lt;/a&gt; is the only exit authorization; without it an arbitrary caller could exit any builder.&lt;/p&gt;

&lt;h3 id=&quot;signing-domain-separation&quot;&gt;Signing-domain separation&lt;/h3&gt;

&lt;p&gt;Builder deposits are signed under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMAIN_BUILDER_DEPOSIT&lt;/code&gt;, distinct from the validator &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMAIN_DEPOSIT&lt;/code&gt;, so deposit proofs-of-possession cannot be replayed across the two classes. Fork-transition seed deposits are made through the validator deposit contract and are necessarily signed under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMAIN_DEPOSIT&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;replayable-deposit-records&quot;&gt;Replayable deposit records&lt;/h3&gt;

&lt;p&gt;A deposit’s fields are public in calldata, so a third party can resubmit them for an already-registered builder at an amount it funds itself. Such a replay is a top-up whose credentials and signature are ignored. It credits stake and redirects nothing.&lt;/p&gt;

&lt;h3 id=&quot;custodial-split-exit-standoff&quot;&gt;Custodial-split exit standoff&lt;/h3&gt;

&lt;p&gt;Exit requires a zero pending balance, every winning bid adds pending balance, and only the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_address&lt;/code&gt; can authorize exit. Where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execution_address&lt;/code&gt; (capital owner) and the BLS key (bidding operator) are held by different parties, an operator that keeps winning bids can indefinitely block the owner’s exit. Delegating parties should retain off-chain control over the operator’s bidding.&lt;/p&gt;

&lt;h3 id=&quot;spam-and-state-growth&quot;&gt;Spam and state growth&lt;/h3&gt;

&lt;p&gt;The per-block caps bound the drain rate, not enqueue, so the in-state queues can grow across blocks. Growth is gated by value, since each deposit locks at least &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILDER_MIN_DEPOSIT&lt;/code&gt; plus the fee. An attacker submitting valid proofs-of-possession forfeits nothing, because the stake remains a withdrawable builder balance, so post-fork onboarding can be delayed behind a backlog of attacker deposits at the cost of locked capital. This is tolerable because the time-critical initial builder set is seeded through the fork transition rather than the steady-state contract.&lt;/p&gt;

&lt;h3 id=&quot;locked-funds&quot;&gt;Locked funds&lt;/h3&gt;

&lt;p&gt;The request fee, any overpayment, and the principal of a first deposit that the consensus layer rejects for an invalid proof-of-possession are permanently locked in the predeploy. The execution layer does not verify BLS signatures, so the off-chain proof-of-possession check advised in &lt;a href=&quot;#deposit-requests&quot;&gt;Deposit requests&lt;/a&gt; is a submitter’s only protection against losing a first deposit’s principal.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8282</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8282</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Asset Anchor Registry</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8325 - Asset Anchor Registry&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-04. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8325-asset-anchor-registry/28934&quot;&gt;https://ethereum-magicians.org/t/erc-8325-asset-anchor-registry/28934&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines interfaces for registries that
bind token contracts or token IDs to anchor records representing claims about
off-chain assets. Each anchor
contains separate commitments to a claimed legal basis and supporting evidence.
Bindings distinguish whole-contract scope from token-ID scope, enforce
registry-scoped exclusivity, and preserve immutable binding history.&lt;/p&gt;

&lt;p&gt;Token-side interfaces allow contracts to declare the same registry and anchor,
enabling consumers to verify both sides of a binding. A lifecycle interface
defines structured metadata, expiry, re-attestation, and permanent
deactivation. An optional recovery interface permits disputed bindings to be
invalidated without deleting their historical records.&lt;/p&gt;

&lt;p&gt;The resulting records provide durable, registry-scoped binding provenance for
consumers that require an auditable lifecycle history.&lt;/p&gt;

&lt;p&gt;This ERC does not establish the existence, ownership, legal validity, or value
of an off-chain asset.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;A token can claim in metadata that it represents an off-chain asset, but that
claim does not provide a common interface for another contract to determine:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;which registry record the token claims;&lt;/li&gt;
  &lt;li&gt;whether the registry records the same token-to-anchor relationship;&lt;/li&gt;
  &lt;li&gt;whether the binding is exclusive within that registry;&lt;/li&gt;
  &lt;li&gt;whether the binding applies to an entire token contract or one token ID; or&lt;/li&gt;
  &lt;li&gt;whether the anchor is active, expired, deactivated, or invalidated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deployments subject to institutional or regulatory oversight often need a
durable answer to which token tuple was recorded against an asset claim, when
the binding was established, and whether it remains current. This ERC makes
registry-scoped exclusivity and immutable binding history explicit without
asserting that the underlying claim is legally valid or factually correct.&lt;/p&gt;

&lt;p&gt;Without a mutually queryable structure, the relationship remains
assertion-only tokenization: the token can describe an off-chain asset, but an
independent consumer cannot verify the claimed token-to-record relationship
through a common interface.&lt;/p&gt;

&lt;p&gt;Applications consequently rely on implementation-specific metadata and
registries. The same asset claim can be represented differently by each issuer,
and consumers cannot inspect a binding through a common interface.&lt;/p&gt;

&lt;p&gt;This ERC standardizes the structural relationship between a registry anchor
and a token contract or token ID. The guarantee is intentionally limited to one
registry instance. Registry operators remain responsible for deciding which
claims they accept, and consumers remain responsible for deciding which
registries they trust.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;Request for Comments (RFC) 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;definitions&quot;&gt;Definitions&lt;/h3&gt;

&lt;p&gt;An &lt;strong&gt;anchor&lt;/strong&gt; is a registry record containing commitments and metadata for an
off-chain asset claim.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;contract binding&lt;/strong&gt; binds an anchor to an entire token contract. This is
appropriate when one contract represents one claimed asset or instrument.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;token-ID binding&lt;/strong&gt; binds an anchor to one token ID within a token contract.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;binding tuple&lt;/strong&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(token, bindingScope, tokenId)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;valid binding&lt;/strong&gt; is a recorded binding that has not been invalidated through
the optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAssetAnchorRegistryRecovery&lt;/code&gt; interface, defined in the
&lt;a href=&quot;#recovery-interface&quot;&gt;Recovery Interface&lt;/a&gt; section below. Binding validity is
distinct from lifecycle activity.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;active anchor&lt;/strong&gt; is an anchor that has not been permanently deactivated and
whose metadata has not expired.&lt;/p&gt;

&lt;h3 id=&quot;binding-scopes&quot;&gt;Binding Scopes&lt;/h3&gt;

&lt;p&gt;Implementations MUST use the following scope identifiers:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BINDING_SCOPE_CONTRACT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8325:BINDING_SCOPE:CONTRACT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BINDING_SCOPE_TOKEN_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8325:BINDING_SCOPE:TOKEN_ID&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BINDING_SCOPE_CONTRACT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tokenId&lt;/code&gt; MUST equal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; as a canonical unused
value.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BINDING_SCOPE_TOKEN_ID&lt;/code&gt;, every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt; value is valid, including token ID
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;. Token ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; MUST NOT be interpreted as a contract-binding sentinel.&lt;/p&gt;

&lt;h3 id=&quot;metadata-encoding&quot;&gt;Metadata Encoding&lt;/h3&gt;

&lt;p&gt;Registration metadata MUST be application binary interface (ABI) encoded as
the following ordered tuple:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorMetadata&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jurisdiction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The canonical encoding is:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jurisdiction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attestationDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jurisdiction&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestationDate&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; and MUST NOT be later than
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expiresAt&lt;/code&gt; MUST be later than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestationDate&lt;/code&gt; and MUST NOT
be earlier than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; at registration. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uri&lt;/code&gt; MUST NOT be empty.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extensions&lt;/code&gt; MAY be empty.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt; SHOULD be a domain-separated identifier from a documented
taxonomy. When an anchor has one primary country jurisdiction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jurisdiction&lt;/code&gt;
SHOULD be a domain-separated identifier derived from its uppercase
International Organization for Standardization (ISO) 3166-1
alpha-2 code.&lt;/p&gt;

&lt;p&gt;The Uniform Resource Identifier (URI) identifies where a consumer can retrieve
material corresponding to the anchor commitments. This ERC does not require a
particular URI scheme or guarantee availability.&lt;/p&gt;

&lt;h3 id=&quot;registry-interface&quot;&gt;Registry Interface&lt;/h3&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetAnchorRegistry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorRecord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boundToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boundTokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registeredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorRegistered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TokenBound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorDeactivated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reason&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorReattested&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldExpiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newExpiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newAttestationDate&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registerAnchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registerAndBind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAnchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnchorRecord&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isBound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;registration&quot;&gt;Registration&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerAnchor&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerAndBind&lt;/code&gt; MUST reject &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;legalHash&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The anchor identifier MUST be derived as:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(legalHash, evidenceHash)&lt;/code&gt; pair therefore produces the same
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; within and across implementations of this ERC. A registry MUST
reject an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; that it has already registered.&lt;/p&gt;

&lt;p&gt;On successful registration, the registry MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;store the supplied hashes and derived &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;store &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registeredAt&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundToken&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address(0)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindingScope&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundTokenId&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorRegistered&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The mechanism for authorizing registration is implementation-defined.
Implementations MUST document their authorization policy.&lt;/p&gt;

&lt;h3 id=&quot;binding&quot;&gt;Binding&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindToken&lt;/code&gt; MUST reject an unknown anchor, an inactive or expired anchor, a zero
token address, an unsupported binding scope, and an anchor whose binding fields
have already been set.&lt;/p&gt;

&lt;p&gt;Before recording a binding, the registry MUST ensure that no valid anchor is
already associated with the same binding tuple. The uniqueness key SHOULD be
derived as:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On successful binding, the registry MUST set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundToken&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindingScope&lt;/code&gt;, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundTokenId&lt;/code&gt; and emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenBound&lt;/code&gt;. These three historical fields MUST NOT be
modified after they are set, including after deactivation or invalidation.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerAndBind&lt;/code&gt; MUST apply the same registration and binding requirements
atomically.&lt;/p&gt;

&lt;p&gt;The mechanism for authorizing binding is implementation-defined. It MUST
prevent an unrelated caller from binding another registrar’s unbound anchor.&lt;/p&gt;

&lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;token&lt;/code&gt; exposes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorRegistry()&lt;/code&gt;, the returned address MUST equal the
registry performing the binding. A registry MAY bind a token that does not
implement a token-side interface. Such a record is a registry-side binding only
and does not constitute mutually declared binding under this ERC.&lt;/p&gt;

&lt;h3 id=&quot;registry-queries&quot;&gt;Registry Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAnchor&lt;/code&gt; MUST return the complete stored record and MUST revert for an
unknown &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBound&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundToken&lt;/code&gt; is not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address(0)&lt;/code&gt;, regardless
of lifecycle activity or recovery invalidation. It MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; for a
known but unbound anchor and MUST revert for an unknown &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;lifecycle-interface&quot;&gt;Lifecycle Interface&lt;/h3&gt;

&lt;p&gt;Every compliant registry MUST implement the lifecycle interface because anchor
activity and expiry are part of the common verification model:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetAnchorRegistryLifecycle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getMetadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnchorMetadata&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registeredBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isActive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deactivateAnchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reason&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reattest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newExpiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newAttestationDate&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getMetadata&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registeredBy&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isActive&lt;/code&gt; MUST revert for an unknown
anchor.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registeredBy&lt;/code&gt; MUST return the address that successfully registered the anchor
and MUST NOT change after registration.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isActive&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorRecord.active&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; or if
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;gt; expiresAt&lt;/code&gt;. An anchor remains active at the exact
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expiresAt&lt;/code&gt; timestamp.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deactivateAnchor&lt;/code&gt; MUST be restricted to authorized callers, set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;, and emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorDeactivated&lt;/code&gt;. Manual deactivation is permanent and
MUST NOT be reversed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reattest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reattest&lt;/code&gt; MUST be restricted to an authorized caller and MUST reject a
manually deactivated anchor. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newAttestationDate&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;, later than
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;, or earlier than the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestationDate&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newExpiresAt&lt;/code&gt; MUST be later than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;, later than
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newAttestationDate&lt;/code&gt;, and not earlier than the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expiresAt&lt;/code&gt;. Successful
re-attestation MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorReattested&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;recovery-interface&quot;&gt;Recovery Interface&lt;/h3&gt;

&lt;p&gt;Binding recovery is OPTIONAL. A registry that permits disputed bindings to be
invalidated MUST implement:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetAnchorRegistryRecovery&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TokenBindingInvalidated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalidateTokenBinding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isBindingValid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;invalidateTokenBinding&lt;/code&gt; MUST be restricted to an authorized recovery role. It
MUST reject an unknown, unbound, or previously invalidated anchor and a zero
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reasonHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Successful invalidation MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;preserve &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundToken&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindingScope&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundTokenId&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBindingValid(anchorId)&lt;/code&gt; return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;permanently deactivate the anchor;&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorDeactivated&lt;/code&gt; if the anchor was active; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenBindingInvalidated&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An implementation MAY free the binding tuple so that a different anchor can be
bound to it. If it does so, the invalidated record MUST remain historically
queryable and MUST NOT itself be rebound.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBindingValid&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; only when an anchor is bound and has not
been invalidated. It MUST revert for an unknown anchor.&lt;/p&gt;

&lt;h3 id=&quot;token-interfaces&quot;&gt;Token Interfaces&lt;/h3&gt;

&lt;p&gt;Whole-contract bindings use:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetBoundToken&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC165&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorRegistry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isAnchorActive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Token-ID bindings use:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetBoundTokenId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC165&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorIdOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorRegistry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isAnchorActiveFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorRegistry&lt;/code&gt; MUST remain unchanged after deployment.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAssetBoundToken&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; MUST remain unchanged after deployment.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAssetBoundTokenId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorIdOf(tokenId)&lt;/code&gt; MUST revert when the token ID is
not bound. Once a nonzero anchor is declared for a token ID, that declaration
MUST NOT change.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isAnchorActive&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isAnchorActiveFor&lt;/code&gt; MUST reflect lifecycle activity from
the declared registry. Consumers MUST query &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBindingValid&lt;/code&gt; separately when
the registry implements the recovery interface.&lt;/p&gt;

&lt;h3 id=&quot;interface-detection&quot;&gt;Interface Detection&lt;/h3&gt;

&lt;p&gt;Compliant registries MUST implement &lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IAssetAnchorRegistry).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Compliant registries MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IAssetAnchorRegistryLifecycle).interfaceId&lt;/code&gt;. Registries implementing
recovery MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IAssetAnchorRegistryRecovery).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Compliant tokens MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for the applicable token-side interface ID.&lt;/p&gt;

&lt;p&gt;ERC-165 detects interface support. It does not prove correct behavior, transfer
enforcement, registrar trustworthiness, or the validity of an off-chain claim.&lt;/p&gt;

&lt;h3 id=&quot;complete-binding-verification&quot;&gt;Complete Binding Verification&lt;/h3&gt;

&lt;p&gt;A consumer treating a binding as mutually declared MUST verify all of the
following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAnchor(anchorId)&lt;/code&gt; returns the expected token, scope, and token ID.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBound(anchorId)&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isActive(anchorId)&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBindingValid(anchorId)&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; when recovery is implemented.&lt;/li&gt;
  &lt;li&gt;The token supports the applicable token-side interface.&lt;/li&gt;
  &lt;li&gt;The token reports the same registry and anchor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Failure of any applicable check means the consumer MUST NOT treat the binding
as a current mutually declared binding.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;why-use-a-registry&quot;&gt;Why Use a Registry?&lt;/h3&gt;

&lt;p&gt;A separate registry allows the same binding interface to compose with fungible,
non-fungible, multi-token, permissioned, and future token standards. It also
provides one inspection surface for applications that do not control the token
implementation.&lt;/p&gt;

&lt;p&gt;The registry does not create global truth. Consumers select which registry
operators and authorization policies they trust.&lt;/p&gt;

&lt;h3 id=&quot;why-two-hashes&quot;&gt;Why Two Hashes?&lt;/h3&gt;

&lt;p&gt;Off-chain asset structures often distinguish the instrument or legal basis
from evidence about the referenced asset. Separate commitments preserve that
distinction without assigning universal semantics to either document set.&lt;/p&gt;

&lt;p&gt;Deployments that do not need the distinction can commit to two separately
defined records. A zero hash is not available as an omission sentinel.&lt;/p&gt;

&lt;h3 id=&quot;why-a-deterministic-anchor-identifier&quot;&gt;Why a Deterministic Anchor Identifier?&lt;/h3&gt;

&lt;p&gt;Deriving &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; from both commitments gives implementations the same
identifier for the same pair of bytes and makes duplicate registration within a
registry unambiguous. It does not deduplicate semantically equivalent documents
with different byte representations.&lt;/p&gt;

&lt;h3 id=&quot;why-explicit-binding-scope&quot;&gt;Why Explicit Binding Scope?&lt;/h3&gt;

&lt;p&gt;Using token ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; to mean whole-contract binding prevents token ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; from
being bound as an actual &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt; or
&lt;a href=&quot;/EIPS/eip-1155&quot;&gt;ERC-1155&lt;/a&gt; token. Including an explicit scope makes contract
binding and token-ID-zero binding distinct.&lt;/p&gt;

&lt;h3 id=&quot;why-split-the-token-interfaces&quot;&gt;Why Split the Token Interfaces?&lt;/h3&gt;

&lt;p&gt;A whole-contract token has no meaningful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorIdOf&lt;/code&gt; query, while a collection
with independently anchored token IDs has no meaningful contract-wide
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt;. Separate interfaces avoid mandatory functions with misleading or
implementation-specific failure behavior.&lt;/p&gt;

&lt;h3 id=&quot;why-separate-activity-from-binding&quot;&gt;Why Separate Activity from Binding?&lt;/h3&gt;

&lt;p&gt;A binding is historical identity data. Activity is lifecycle status. Expiry or
deactivation can make an anchor operationally inactive without changing which
token was bound to it. Accordingly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBound&lt;/code&gt; is not an activity check.&lt;/p&gt;

&lt;h3 id=&quot;why-an-optional-recovery-interface&quot;&gt;Why an Optional Recovery Interface?&lt;/h3&gt;

&lt;p&gt;Permanent bindings are vulnerable to registrar compromise, key loss, and
binding-key squatting. Recovery allows an explicitly trusted administrator to
invalidate an operational binding while preserving its history. Deployments
that prefer absolute immutability can omit the recovery interface.&lt;/p&gt;

&lt;p&gt;Recovery introduces substantial administrative trust and is therefore not part
of the minimum registry interface.&lt;/p&gt;

&lt;h3 id=&quot;why-not-enforce-allocation-integrity&quot;&gt;Why Not Enforce Allocation Integrity?&lt;/h3&gt;

&lt;p&gt;Allocation constraints, such as ensuring that fractional token supply does not
represent more than a defined share of an asset, depend on the economic and
legal structure of the instrument. They are meaningful for some fungible
fractional claims but not for a single non-fungible token (NFT) representing one
object or for a registry record that does not express ownership percentages.&lt;/p&gt;

&lt;p&gt;The registry therefore standardizes binding identity rather than issuance or
allocation rules. Tokens and application-specific contracts remain responsible
for enforcing any supply, fraction, or entitlement constraints.&lt;/p&gt;

&lt;h3 id=&quot;why-leave-registry-governance-open&quot;&gt;Why Leave Registry Governance Open?&lt;/h3&gt;

&lt;p&gt;Different deployments require different trust models. A registry may be
operated by one accountable issuer, a regulated registrar, a multisignature, a
decentralized autonomous organization (DAO), or a permissionless protocol.
Requiring one governance model would exclude
otherwise interoperable implementations without making their off-chain claims
more truthful.&lt;/p&gt;

&lt;p&gt;Consumers select which registries and governance policies they trust. The
common interface makes those registries technically inspectable; it does not
make them equally trustworthy.&lt;/p&gt;

&lt;h3 id=&quot;why-are-historical-binding-fields-immutable&quot;&gt;Why Are Historical Binding Fields Immutable?&lt;/h3&gt;

&lt;p&gt;Changing a binding’s token, scope, or token ID in place would erase the
relationship that consumers previously inspected. This ERC therefore preserves
those fields after deactivation and recovery invalidation, allowing auditors
and other consumers to determine which tuple was recorded and how its status
changed over time.&lt;/p&gt;

&lt;p&gt;Field immutability does not mean that a binding remains active or valid.
Consumers must evaluate lifecycle activity and, when implemented, recovery
validity separately. If an implementation releases an invalidated tuple, the
invalidated record remains queryable and a replacement is stored as a separate
anchor. The guarantee remains scoped to one registry and does not establish
global one-token-to-one-asset uniqueness.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-3643&quot;&gt;ERC-3643&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-7943&quot;&gt;ERC-7943&lt;/a&gt; define token behavior and
compliance-related interfaces. They do not define the registry-scoped
token-to-anchor relationship specified here. Tokens implementing either can
also implement a token-side interface from this ERC.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This ERC introduces new interfaces and does not change existing token
standards. Existing token contracts can be recorded in a registry without
modification, but this produces only a registry-side binding.&lt;/p&gt;

&lt;p&gt;An existing upgradeable token can add the applicable token-side interface. An
immutable token that lacks the interface requires a wrapper, adapter, or new
deployment to provide mutually declared binding. Consumers should distinguish a
registry-only record from a binding confirmed by both registry and token.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Implementations should test at least the following cases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;deterministic anchor derivation and duplicate rejection;&lt;/li&gt;
  &lt;li&gt;rejection of zero hashes and malformed metadata;&lt;/li&gt;
  &lt;li&gt;contract scope with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tokenId == 0&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;rejection of contract scope with a nonzero token ID;&lt;/li&gt;
  &lt;li&gt;token-ID scope with token ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;separation of contract scope from token-ID-zero scope;&lt;/li&gt;
  &lt;li&gt;rejection of duplicate anchor and duplicate valid binding tuple use;&lt;/li&gt;
  &lt;li&gt;atomic registration and binding;&lt;/li&gt;
  &lt;li&gt;expiry at, before, and after the inclusive boundary;&lt;/li&gt;
  &lt;li&gt;permanent manual deactivation;&lt;/li&gt;
  &lt;li&gt;monotonic re-attestation;&lt;/li&gt;
  &lt;li&gt;token registry mismatch;&lt;/li&gt;
  &lt;li&gt;complete mutually declared binding verification across registry and
token-side queries;&lt;/li&gt;
  &lt;li&gt;preservation of binding fields across deactivation and recovery invalidation;&lt;/li&gt;
  &lt;li&gt;lifecycle event coverage for registration, binding, re-attestation,
deactivation, and recovery invalidation;&lt;/li&gt;
  &lt;li&gt;optional release of an invalidated binding tuple; and&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;A Solidity reference implementation, unit tests, fuzz tests, invariants, and an
independent audit are linked from the discussion referenced in the preamble.
The implementation is illustrative; its access-control roles and deployment
model are not required by this ERC.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;registry-trust&quot;&gt;Registry Trust&lt;/h3&gt;

&lt;p&gt;The registry proves only that its own state satisfies the specified structural
rules. A malicious or compromised registrar can register false claims with
validly formed hashes and metadata. Consumers should evaluate the registry’s
operator, authorization policy, upgrade authority, and legal context.&lt;/p&gt;

&lt;h3 id=&quot;no-legal-or-physical-truth-guarantee&quot;&gt;No Legal or Physical Truth Guarantee&lt;/h3&gt;

&lt;p&gt;Neither a hash nor a mutually declared token binding proves that an off-chain
asset exists, that documents are authentic, or that a token conveys a legal
right. Those determinations require external verification.&lt;/p&gt;

&lt;h3 id=&quot;registration-to-binding-races&quot;&gt;Registration-to-Binding Races&lt;/h3&gt;

&lt;p&gt;Separate registration and binding create an interval in which an unauthorized
caller may attempt to bind an anchor. Implementations should restrict binding to
authorized parties. Registrars should use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerAndBind&lt;/code&gt; when atomicity is
required.&lt;/p&gt;

&lt;h3 id=&quot;malicious-tokens-and-interface-spoofing&quot;&gt;Malicious Tokens and Interface Spoofing&lt;/h3&gt;

&lt;p&gt;A token can return arbitrary values from the token-side interfaces or falsely
claim ERC-165 support. Consumers should verify the registry record independently.
Registries that call token contracts during binding should use static calls and
handle malformed return data and reverts.&lt;/p&gt;

&lt;h3 id=&quot;recovery-authority&quot;&gt;Recovery Authority&lt;/h3&gt;

&lt;p&gt;A recovery administrator can invalidate legitimate bindings and, when the
implementation releases binding tuples, enable replacement anchors. Production
deployments should protect recovery authority with a multisignature,
governance, timelock, or equivalent controls. Consumers should monitor
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenBindingInvalidated&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorDeactivated&lt;/code&gt; events.&lt;/p&gt;

&lt;p&gt;Releasing an invalidated tuple does not change an immutable token-side anchor
declaration. A replacement can be mutually declared only when the token already
declares the replacement anchor. A replacement binding recorded for a token that
does not expose a token-side interface is registry-side only.&lt;/p&gt;

&lt;h3 id=&quot;document-canonicalization&quot;&gt;Document Canonicalization&lt;/h3&gt;

&lt;p&gt;The registry treats &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;legalHash&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceHash&lt;/code&gt; as opaque commitments. Two
representations of the same document can produce different hashes. Deployments
requiring interoperable document commitments should define a deterministic
normalization and bundle-hashing procedure.&lt;/p&gt;

&lt;h3 id=&quot;data-availability&quot;&gt;Data Availability&lt;/h3&gt;

&lt;p&gt;An on-chain commitment is not useful for verification if the committed material
cannot be retrieved. The registry does not guarantee URI persistence or data
availability. Deployments should use durable storage and availability policies.&lt;/p&gt;

&lt;h3 id=&quot;multi-registry-and-cross-chain-duplication&quot;&gt;Multi-Registry and Cross-Chain Duplication&lt;/h3&gt;

&lt;p&gt;Independent registries or deployments on different chains can register claims
about the same off-chain asset. This ERC provides no global uniqueness or
cross-registry conflict resolution.&lt;/p&gt;

&lt;p&gt;Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; does not include a chain identifier or registry address,
consumers requiring globally scoped identity should use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(chainId, registry, anchorId)&lt;/code&gt; rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; alone. A companion system
that accepts only a bare &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; can otherwise conflate records from
different registry domains.&lt;/p&gt;

&lt;h3 id=&quot;expiry-and-timestamp-dependence&quot;&gt;Expiry and Timestamp Dependence&lt;/h3&gt;

&lt;p&gt;Lifecycle status depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;, which block producers can vary
within protocol constraints. Applications should avoid relying on second-level
precision around an expiry boundary.&lt;/p&gt;

&lt;h3 id=&quot;upgradeability&quot;&gt;Upgradeability&lt;/h3&gt;

&lt;p&gt;An upgradeable registry can alter binding behavior after consumers begin
relying on it. Upgrades must preserve historical binding fields to remain
compliant. Consumers should inspect proxy administration and upgrade policies.&lt;/p&gt;

&lt;h3 id=&quot;institutional-and-regulated-deployments&quot;&gt;Institutional and Regulated Deployments&lt;/h3&gt;

&lt;p&gt;Deployments operating under institutional or regulatory controls should
document registration and binding authority, protect recovery and upgrade
authority with appropriate multisignature, timelock, governance, or equivalent
controls, and monitor all binding and lifecycle events.&lt;/p&gt;

&lt;p&gt;Such deployments should also define how contested invalidations are reviewed
and how committed records are made available to authorized auditors. Conformance
with this ERC provides a common technical interface; it does not establish
regulatory status, legal sufficiency, or compliance with any jurisdiction’s
requirements.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sat, 04 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8325</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8325</guid>
      </item>
      
    
      
      
      <item>
        <title>Canonical Document Bundle Anchor</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8326 - Canonical Document Bundle Anchor&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8326-canonical-document-bundle-anchor/28935&quot;&gt;https://ethereum-magicians.org/t/erc-8326-canonical-document-bundle-anchor/28935&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines a deterministic manifest and
anchoring interface for commitments to bundles of off-chain documents. Each
document is represented by
a fixed-width entry containing a content hash, document role, media-type hash,
filename hash, and normalization-profile identifier. Entries are placed in a
total order and hashed under a schema-version prefix to produce one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt;
bundle commitment.&lt;/p&gt;

&lt;p&gt;The on-chain interface anchors a bundle hash in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, role)&lt;/code&gt; namespace,
records declarative metadata, and preserves an append-only supersession history.
An optional recovery interface permits administrative reassignment of authority
over a contested namespace without rewriting anchored records.&lt;/p&gt;

&lt;p&gt;This ERC standardizes manifest construction and commitment anchoring. It does
not prove document authenticity, legal effect, off-chain availability, or the
correct application of a normalization profile.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Contracts and applications frequently commit to multiple off-chain documents,
including agreements, certifications, evidence, amendments, and supporting
records. Without a common manifest, implementations differ in entry encoding,
ordering, version separation, and supersession behavior. Two systems can hold
the same canonical document representations but derive incompatible bundle
commitments.&lt;/p&gt;

&lt;p&gt;Document commitment has two distinct layers. Normalization transforms a raw
format into canonical bytes. Manifesting describes and orders the resulting
document commitments before deriving a bundle hash. Normalization is
format-specific and evolves independently; manifesting and on-chain anchoring
can remain stable.&lt;/p&gt;

&lt;p&gt;This ERC provides a common manifest and anchoring surface while making that
boundary explicit. Compatible implementations derive the same bundle hash only
when they use the same canonical document bytes, entry fields, normalization
profile identifiers, schema version, and ordering rules.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;definitions&quot;&gt;Definitions&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;document entry&lt;/strong&gt; is a fixed-width record describing one normalized document
commitment.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;normalization profile&lt;/strong&gt; defines how raw document input is converted to the
bytes committed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contentHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;bundle&lt;/strong&gt; is a non-empty multiset of document entries. Duplicate entries are
retained and affect the resulting bundle hash.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;bundle hash&lt;/strong&gt; is the schema-versioned commitment derived from the canonically
ordered entries.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;slot&lt;/strong&gt; is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, role)&lt;/code&gt; namespace containing at most one active
bundle hash.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;superseded record&lt;/strong&gt; is a historical anchor that has been replaced in its
slot. Supersession does not delete or rewrite its immutable fields.&lt;/p&gt;

&lt;h3 id=&quot;document-entry&quot;&gt;Document Entry&lt;/h3&gt;

&lt;p&gt;Each document MUST be represented as:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DocumentEntry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mimeTypeHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filenameHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normProfileId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contentHash&lt;/code&gt; MUST be the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; hash of the exact output bytes produced by
the selected normalization profile.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt; identifies the function of the document within the bundle.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mimeTypeHash&lt;/code&gt; MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; of the canonical IANA media type encoded as
lowercase ASCII without parameters. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;application/json;
charset=utf-8&lt;/code&gt; is represented by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(&quot;application/json&quot;)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filenameHash&lt;/code&gt; MUST be derived by treating U+002F (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;) and U+005C (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt;) as
path separators, retaining the substring after the final separator, applying
ASCII lowercase conversion to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Z&lt;/code&gt;, applying Unicode NFC
normalization, encoding the result as UTF-8, and applying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;normProfileId&lt;/code&gt; identifies the transformation used to produce the committed
bytes. Consumers MUST NOT interpret &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contentHash&lt;/code&gt; without considering its
normalization profile.&lt;/p&gt;

&lt;h3 id=&quot;schema-role-and-profile-identifiers&quot;&gt;Schema, Role, and Profile Identifiers&lt;/h3&gt;

&lt;p&gt;Implementations MUST use the following schema identifier:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCHEMA_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8326:BUNDLE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The following role identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LEGAL_BASIS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;LEGAL_BASIS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVIDENCE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EVIDENCE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CERTIFICATION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CERTIFICATION&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AGREEMENT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AGREEMENT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AMENDMENT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AMENDMENT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUPPORTING&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;SUPPORTING&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Applications MAY define additional role identifiers. Custom roles SHOULD use a
documented namespace and version to prevent semantic collisions.&lt;/p&gt;

&lt;p&gt;The following normalization profiles are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROFILE_RAW&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;NORM:RAW:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROFILE_JSON_RFC8785&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;NORM:JSON:RFC8785:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROFILE_XML_C14N11&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;NORM:XML:C14N11:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_RAW&lt;/code&gt;, the output bytes are the raw input bytes without
transformation.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_JSON_RFC8785&lt;/code&gt;, the output bytes are the UTF-8 serialization
produced by &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8785&quot;&gt;RFC 8785&lt;/a&gt;. Implementations
MUST reject inputs that cannot be processed under the RFC 8785 and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7493&quot;&gt;I-JSON&lt;/a&gt; constraints, including
duplicate object keys, invalid Unicode, lone surrogates, and numbers outside
the interoperable range. JSON string values are preserved;
this profile does not apply Unicode normalization to them.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_XML_C14N11&lt;/code&gt;, the output bytes are produced by
&lt;a href=&quot;https://www.w3.org/TR/2008/REC-xml-c14n11-20080502/&quot;&gt;Canonical XML 1.1&lt;/a&gt;
without comments. Implementations MUST disable external entity resolution.
This profile is distinct from Exclusive XML Canonicalization.&lt;/p&gt;

&lt;p&gt;PDF, image, signed-PDF, and plain-text normalization are not defined by this
ERC. Such documents SHOULD use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_RAW&lt;/code&gt; unless another precisely specified
profile is agreed by the producer and verifier.&lt;/p&gt;

&lt;p&gt;Custom profile identifiers SHOULD use:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NORM:CUSTOM:&amp;lt;namespace&amp;gt;:&amp;lt;format&amp;gt;:&amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A custom profile specification MUST define exact transformation rules and test
fixtures. The namespace MUST identify the defining organization or protocol.&lt;/p&gt;

&lt;h3 id=&quot;canonical-ordering&quot;&gt;Canonical Ordering&lt;/h3&gt;

&lt;p&gt;Entries MUST be ordered lexicographically by their raw &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; values using
the following keys, each ascending:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filenameHash&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contentHash&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mimeTypeHash&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;normProfileId&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The comparison proceeds to the next key only when all preceding keys are equal.
Equal entries remain duplicated. No timestamp or preparer-controlled value is
included in a document entry.&lt;/p&gt;

&lt;h3 id=&quot;bundle-hash-derivation&quot;&gt;Bundle Hash Derivation&lt;/h3&gt;

&lt;p&gt;A bundle MUST contain at least one entry.&lt;/p&gt;

&lt;p&gt;For each canonically ordered entry, derive:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leaf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contentHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mimeTypeHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filenameHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;normProfileId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The bundle hash is:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SCHEMA_V1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leaf0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leaf1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leafN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All encoded elements are fixed-width &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; values, so packed encoding does
not introduce variable-length boundary ambiguity.&lt;/p&gt;

&lt;p&gt;Future incompatible manifest schemas MUST use a new schema identifier. They
MUST NOT reuse &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SCHEMA_V1&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;reference-hashing-functions&quot;&gt;Reference Hashing Functions&lt;/h3&gt;

&lt;p&gt;The following signatures describe two conforming reference paths:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeCanonicalBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DocumentEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DocumentEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;computeCanonicalBundleHash&lt;/code&gt; MUST sort entries according to the total order
before deriving the hash.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;computeBundleHash&lt;/code&gt; MUST require already sorted entries and MUST revert for
unsorted input. Both functions MUST revert for an empty bundle and MUST produce
the derivation specified above.&lt;/p&gt;

&lt;p&gt;The reference &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;computeCanonicalBundleHash&lt;/code&gt; uses an in-memory quadratic sort for
clarity. Production systems SHOULD normalize, sort, and hash off-chain. Large
bundles verified on-chain SHOULD use pre-sorted entries with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;computeBundleHash&lt;/code&gt; or a more gas-efficient algorithm that produces the same
total order.&lt;/p&gt;

&lt;h3 id=&quot;anchor-interface&quot;&gt;Anchor Interface&lt;/h3&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDocumentBundleAnchor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorRecord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchoredBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchoredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadataURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;superseded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;supersededBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BundleAnchored&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentCount&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BundleSuperseded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadataURI&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;supersedeBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadataURI&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAnchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnchorRecord&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isAnchored&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;activeBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;anchoring&quot;&gt;Anchoring&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorBundle&lt;/code&gt; MUST reject a zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundleHash&lt;/code&gt;, zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt;, or
zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadataURI&lt;/code&gt; MAY be empty. An empty value indicates that the anchor does not
provide an on-chain retrieval pointer. Applications requiring availability
SHOULD enforce a non-empty URI before calling the registry.&lt;/p&gt;

&lt;p&gt;Applications without an existing subject identifier SHOULD derive a nonzero,
domain-separated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; from application context rather than sharing a
common placeholder value.&lt;/p&gt;

&lt;p&gt;Each record MUST be keyed by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(bundleHash, subjectId, role)&lt;/code&gt; triple. The same
bundle hash MAY be anchored under different subjects or roles, producing
independent records.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorBundle&lt;/code&gt; MUST reject a duplicate triple and MUST reject a slot that already
has an active bundle. Replacement of an occupied slot MUST use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersedeBundle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, the registry MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;store all supplied values;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchoredBy&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchoredAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;superseded&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersededBy&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set the active bundle for the slot; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BundleAnchored&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The registry MUST restrict anchoring to authorized callers. Its authorization
mechanism is implementation-defined and MUST be documented.&lt;/p&gt;

&lt;h3 id=&quot;supersession&quot;&gt;Supersession&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersedeBundle&lt;/code&gt; MUST reject a zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newBundleHash&lt;/code&gt;, zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, zero
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt;, or zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt;. It MUST reject &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldBundleHash ==
newBundleHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The old record MUST exist, MUST NOT already be superseded, and MUST be the active
bundle for the specified slot. The new triple MUST NOT already exist.&lt;/p&gt;

&lt;p&gt;The caller MUST be authorized to supersede that slot. Authorization is
implementation-defined, but an unrelated authorized anchorer MUST NOT be able to
take over another principal’s slot.&lt;/p&gt;

&lt;p&gt;Supersession MUST atomically:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set the old record’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;superseded&lt;/code&gt; field to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersededBy&lt;/code&gt; field to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newBundleHash&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;create the new active record;&lt;/li&gt;
  &lt;li&gt;update the active slot;&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BundleSuperseded&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BundleAnchored&lt;/code&gt; for the new record.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The old record’s remaining fields MUST NOT change and the old record MUST remain
queryable.&lt;/p&gt;

&lt;h3 id=&quot;queries&quot;&gt;Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAnchor&lt;/code&gt; MUST return the complete record for a triple and MUST revert when no
record exists.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isAnchored&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for every existing record, including a
superseded record, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; for an unknown triple.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeBundle&lt;/code&gt; MUST return the active bundle hash for a slot or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; if
the slot has never been occupied.&lt;/p&gt;

&lt;h3 id=&quot;recovery-interface&quot;&gt;Recovery Interface&lt;/h3&gt;

&lt;p&gt;Administrative slot recovery is OPTIONAL. A registry that supports principal
reassignment MUST implement:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDocumentBundleAnchorRecovery&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SlotPrincipalAssigned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;principal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slotPrincipal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assignSlotPrincipal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;principal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slotPrincipal&lt;/code&gt; MUST return the address currently authorized as principal for
the slot or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address(0)&lt;/code&gt; when none is assigned.&lt;/p&gt;

&lt;p&gt;When the recovery extension is implemented, successful first anchoring and
supersession MUST set the slot principal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assignSlotPrincipal&lt;/code&gt; MUST be restricted to an authorized recovery
administrator and MUST reject zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt;, and a zero
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;principal&lt;/code&gt;. Assignment MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SlotPrincipalAssigned&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Principal assignment does not itself grant general anchoring authority. A
designated principal MUST also satisfy the implementation’s authorization
policy before anchoring or superseding.&lt;/p&gt;

&lt;p&gt;If a principal is assigned before first anchoring, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorBundle&lt;/code&gt; MUST reject
any other caller for that slot. After reassignment, the former principal MUST
NOT be able to supersede that slot solely by retaining general anchoring
authority.&lt;/p&gt;

&lt;h3 id=&quot;interface-detection&quot;&gt;Interface Detection&lt;/h3&gt;

&lt;p&gt;Compliant registries MUST implement &lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IDocumentBundleAnchor).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Registries implementing recovery MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IDocumentBundleAnchorRecovery).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ERC-165 reports interface support. It does not establish that a bundle was
derived correctly, that referenced documents are authentic or available, or
that an operator is trustworthy.&lt;/p&gt;

&lt;h3 id=&quot;consumer-verification&quot;&gt;Consumer Verification&lt;/h3&gt;

&lt;p&gt;A consumer relying on an active bundle MUST:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Query &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeBundle(subjectId, role)&lt;/code&gt; and reject &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Retrieve the corresponding record with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAnchor(bundleHash, subjectId, role)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Verify that the returned fields match the requested hash, subject, and role.&lt;/li&gt;
  &lt;li&gt;Verify that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchoredAt&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt; are nonzero.&lt;/li&gt;
  &lt;li&gt;Verify that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;superseded&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Reproduce the manifest, canonical ordering, and bundle hash off-chain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt; is declarative and MUST NOT be treated as independently verified
by the anchoring contract.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;why-separate-manifesting-from-normalization&quot;&gt;Why Separate Manifesting from Normalization?&lt;/h3&gt;

&lt;p&gt;Combining universal document normalization with bundle hashing would overstate
what one ERC can guarantee. The manifest gives normalized document commitments
a common structure. Profiles define how a particular input format produces the
committed bytes and can evolve independently.&lt;/p&gt;

&lt;h3 id=&quot;why-a-total-order-over-all-five-fields&quot;&gt;Why a Total Order Over All Five Fields?&lt;/h3&gt;

&lt;p&gt;Ordering by only role, filename, and content leaves insertion order as a hidden
tie-breaker when entries differ only by media type or normalization profile.
Including all five fields gives every distinct entry a deterministic position.&lt;/p&gt;

&lt;h3 id=&quot;why-include-a-schema-identifier&quot;&gt;Why Include a Schema Identifier?&lt;/h3&gt;

&lt;p&gt;The schema identifier separates incompatible manifest versions. Without it, a
future change to entry interpretation or hash derivation could reuse the same
hash domain.&lt;/p&gt;

&lt;h3 id=&quot;why-use-subject-and-role-slots&quot;&gt;Why Use Subject and Role Slots?&lt;/h3&gt;

&lt;p&gt;The same document set can be relevant to multiple subjects or serve different
purposes. Keying records by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(bundleHash, subjectId, role)&lt;/code&gt; preserves those
independent records, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, role)&lt;/code&gt; identifies the one current bundle
for a particular purpose.&lt;/p&gt;

&lt;h3 id=&quot;why-permit-an-empty-metadata-uri&quot;&gt;Why Permit an Empty Metadata URI?&lt;/h3&gt;

&lt;p&gt;The bundle commitment remains valid without an on-chain retrieval pointer. Some
deployments distribute documents through private or regulated channels, while
others use content-addressed public storage. Availability policy belongs to the
application and is not implied by a syntactically non-empty URI.&lt;/p&gt;

&lt;h3 id=&quot;why-preserve-superseded-records&quot;&gt;Why Preserve Superseded Records?&lt;/h3&gt;

&lt;p&gt;Document sets evolve through amendments, renewals, and corrections. Mutating or
deleting the prior record would remove the audit trail. Supersession changes
only the prior record’s forward pointer and status.&lt;/p&gt;

&lt;h3 id=&quot;why-a-slot-principal-recovery-extension&quot;&gt;Why a Slot-Principal Recovery Extension?&lt;/h3&gt;

&lt;p&gt;An anchoring key can be compromised, revoked, or used to squat a slot. Directly
attempting an administrative supersession is front-runnable because the current
principal can supersede first and invalidate the administrator’s expected old
hash. Atomic principal reassignment removes that race while preserving all
bundle records.&lt;/p&gt;

&lt;p&gt;Recovery introduces administrative trust, so it is separated from the core
interface. Deployments preferring immutable authority can omit it.&lt;/p&gt;

&lt;h3 id=&quot;why-compute-bundle-hashes-off-chain&quot;&gt;Why Compute Bundle Hashes Off-Chain?&lt;/h3&gt;

&lt;p&gt;Normalization and sorting can be expensive. The reference canonical convenience
path uses a quadratic sort and repeated memory encoding, which is suitable for
tests and small bundles but inefficient for large on-chain sets. The anchoring
contract accepts a precomputed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundleHash&lt;/code&gt;; consumers reproduce it off-chain.&lt;/p&gt;

&lt;h3 id=&quot;why-not-use-a-merkle-root&quot;&gt;Why Not Use a Merkle Root?&lt;/h3&gt;

&lt;p&gt;This ERC commits to the complete ordered manifest and is optimized for
reproducing one bundle identifier, not proving membership of a single document
without the rest of the manifest. Applications requiring compact membership
proofs can commit a separately specified Merkle root as a document or extension
field, but that construction is outside this ERC.&lt;/p&gt;

&lt;h3 id=&quot;why-defer-pdf-and-image-normalization&quot;&gt;Why Defer PDF and Image Normalization?&lt;/h3&gt;

&lt;p&gt;PDF and image files contain format-specific metadata, incremental updates,
compression choices, object ordering, color profiles, and renderer-dependent
behavior. A credible profile requires exact binary fixtures and specialized
review. Until then, byte-identical raw hashing is the only defined profile for
those files.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-5732&quot;&gt;ERC-5732&lt;/a&gt; defines a generic commit-reveal mechanism. It can be
used as a privacy layer around publication but does not define document entries
or bundle hashing.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7208&quot;&gt;ERC-7208&lt;/a&gt; defines general on-chain data containers. This ERC
defines a document-specific commitment and lifecycle interface.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7578&quot;&gt;ERC-7578&lt;/a&gt; includes document URI storage in a physical-asset
redemption flow but does not define deterministic bundle manifesting.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-3668&quot;&gt;ERC-3668&lt;/a&gt; defines an off-chain data retrieval and verification
flow. It can retrieve material referenced by an anchor but does not determine
how a document bundle commitment is derived.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This ERC introduces new interfaces and does not change existing token or
registry standards. Existing systems can store the resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; bundle
hash without changing their storage type, but ad hoc bundle hashes are not
necessarily compatible with this derivation.&lt;/p&gt;

&lt;p&gt;Existing document registries can integrate by storing this bundle hash as a
document commitment or by deploying a companion &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IDocumentBundleAnchor&lt;/code&gt;
registry. Composition with any particular asset registry is optional;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; is an application-defined nonzero identifier.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;raw-byte content hashing;&lt;/li&gt;
  &lt;li&gt;RFC 8785 canonical serialization and invalid-input rejection;&lt;/li&gt;
  &lt;li&gt;Canonical XML 1.1 serialization with external entities disabled;&lt;/li&gt;
  &lt;li&gt;all profile, role, and schema constants;&lt;/li&gt;
  &lt;li&gt;ordering differences at each of the five fields;&lt;/li&gt;
  &lt;li&gt;permutation independence through the canonical hashing path;&lt;/li&gt;
  &lt;li&gt;rejection of unsorted input through the pre-sorted path;&lt;/li&gt;
  &lt;li&gt;empty, single-entry, and duplicate-entry bundles;&lt;/li&gt;
  &lt;li&gt;schema-version separation;&lt;/li&gt;
  &lt;li&gt;anchoring and querying independent triples;&lt;/li&gt;
  &lt;li&gt;rejection of occupied active slots;&lt;/li&gt;
  &lt;li&gt;multi-step supersession history;&lt;/li&gt;
  &lt;li&gt;independent use of the same bundle hash by different subjects or roles;&lt;/li&gt;
  &lt;li&gt;empty and non-empty metadata URIs;&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection; and&lt;/li&gt;
  &lt;li&gt;contested-slot recovery and pre-assignment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;normative-test-vectors&quot;&gt;Normative Test Vectors&lt;/h3&gt;

&lt;p&gt;The hexadecimal byte strings in this section are authoritative. Text renderings
are included only for readability. None of the inputs or canonical outputs has
an implicit byte-order mark or trailing newline unless its hexadecimal form
includes one.&lt;/p&gt;

&lt;p&gt;The schema identifier for these vectors is:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SCHEMA_V1
0x1853dddb0c73884633f2ff8e736679ec654a11f704ed868aacca79d8ae4caf67
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;json-entry&quot;&gt;JSON Entry&lt;/h4&gt;

&lt;p&gt;The filename input contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e&lt;/code&gt; followed by U+0301 COMBINING ACUTE ACCENT.
Filename processing selects the basename, folds ASCII uppercase characters,
and applies NFC, producing the UTF-8 bytes for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;café.json&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;input document:       {&quot;b&quot;:2,&quot;a&quot;:1}
input bytes:          0x7b2262223a322c2261223a317d
canonical document:   {&quot;a&quot;:1,&quot;b&quot;:2}
canonical bytes:      0x7b2261223a312c2262223a327d
filename input:       records/Cafe\u0301.JSON
filename input bytes: 0x7265636f7264732f43616665cc812e4a534f4e
canonical filename:   café.json
filename bytes:       0x636166c3a92e6a736f6e
role preimage:         AGREEMENT
media type preimage:  application/json
profile preimage:     NORM:JSON:RFC8785:V1
contentHash:          0xb8ffb64722137f4b100665a52e3c943f8066e8ab8ba3b427e6f4b404defd82b0
role:                 0x566614d5b403a4ea71e1ef1027b77ff1e1a13a54c7f393aa64a1368de23a5f92
mimeTypeHash:         0x82e6a468c95da6cfe399f69ee0782fd009e354a8030ea5636ea9c7db0edcf7f5
filenameHash:         0x3b40ecd25f3375868ddf559a0ef47c2dc15863a529ac592bec5e1b618bcbaf3e
normProfileId:        0x464861b0846e795db3d9c52e9c49870c7e83f2bb07f73764f7e4850151994f40
leaf:                 0xe78934e3ee972b7eae660a945de9780c77e5656203bfe437ab117413adf3ad2b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;xml-entry&quot;&gt;XML Entry&lt;/h4&gt;

&lt;p&gt;The backslash in the filename input is a path separator. Canonical XML 1.1
orders the unqualified attributes lexicographically. The canonical output has
no trailing newline.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;input document:       &amp;lt;doc b=&quot;2&quot; a=&quot;1&quot;&amp;gt;&amp;lt;/doc&amp;gt;
input bytes:          0x3c646f6320623d22322220613d2231223e3c2f646f633e
canonical document:   &amp;lt;doc a=&quot;1&quot; b=&quot;2&quot;&amp;gt;&amp;lt;/doc&amp;gt;
canonical bytes:      0x3c646f6320613d22312220623d2232223e3c2f646f633e
filename input:       Evidence\Proof.XML
filename input bytes: 0x45766964656e63655c50726f6f662e584d4c
canonical filename:   proof.xml
filename bytes:       0x70726f6f662e786d6c
role preimage:         EVIDENCE
media type preimage:  application/xml
profile preimage:     NORM:XML:C14N11:V1
contentHash:          0xde64c753c807c4620bf010c7e855bcd38bd389e980c4054b81abd5d44d45eab1
role:                 0x7477535acdef313b25d16b4871e7023fac62af68d6312bbdbdb96203a4710dc3
mimeTypeHash:         0x37aaf14a93fea5695fd8577aacfb548c98692a106d439219bfb9b83e3011ea2f
filenameHash:         0x696b36bf7095c1b1564382a37b8f5ba7d259b36be7639a7a1b50c97cd13cfe39
normProfileId:        0x72efa7a47196f4ad021a5a3758b19b14d8e09d7b7b211bf4745b35cba62e49c2
leaf:                 0x8c72daea8a7297c8d307dd41e24038ff71065f9b0932a07e9016942abbc5c9ac
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;raw-entry&quot;&gt;Raw Entry&lt;/h4&gt;

&lt;p&gt;The input and canonical output end with one U+000A LINE FEED byte.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;input document:       Hello, ERC-8326!&amp;lt;LF&amp;gt;
input bytes:          0x48656c6c6f2c204552432d38333236210a
canonical document:   Hello, ERC-8326!&amp;lt;LF&amp;gt;
canonical bytes:      0x48656c6c6f2c204552432d38333236210a
filename input:       README.TXT
filename input bytes: 0x524541444d452e545854
canonical filename:   readme.txt
filename bytes:       0x726561646d652e747874
role preimage:         SUPPORTING
media type preimage:  text/plain
profile preimage:     NORM:RAW:V1
contentHash:          0x06750728a91d155294f77f992fec49acabb0470481439ed5e3bb59854df82ec9
role:                 0xb0e9b5730d97b99270ce15f439eec98a4f9580e1dfbfb8f5c9e0e3ab71d4bca6
mimeTypeHash:         0xb25570cad408307f58d995c1dadde60bc76e94924d640305a148c9a11f8303bf
filenameHash:         0x31f491635b16d6fb45a7d770fcbcc8cbb6eae32ac98ab622631f4bc4a8c7e9ce
normProfileId:        0xbe97b35c60bb0caee86a5a99022973ef2aa47cbf9586dd34065141c6668b430b
leaf:                 0xa418892b0b93cf88e9d840cf38d36f5bfa16813774f22f5cf02d6b4fcc48375a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;bundle-vector&quot;&gt;Bundle Vector&lt;/h4&gt;

&lt;p&gt;The entries sort in JSON, XML, raw order by their &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt; values. Concatenating
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SCHEMA_V1&lt;/code&gt; with the three leaf values in that order produces:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bundleHash:
0xbe712c4a5eb51d9eb303f1a5c896417a8407a420936fa210626bb66b1a6d0613
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;A Solidity reference implementation, hashing library, unit tests, Medusa
property tests, consumer verifier, and independent audit are linked from the
discussion referenced in the preamble. The implementation performs manifest
ordering and hashing over supplied entries; raw JSON and XML normalization
occurs off-chain.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;normalization-profile-trust&quot;&gt;Normalization Profile Trust&lt;/h3&gt;

&lt;p&gt;The determinism guarantee is only as strong as the profile implementation.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_RAW&lt;/code&gt; performs no normalization. Custom profiles can be ambiguous,
malicious, or incompletely specified. Consumers should verify the selected
profile and reproduce the exact transformation.&lt;/p&gt;

&lt;h3 id=&quot;canonicalization-boundary&quot;&gt;Canonicalization Boundary&lt;/h3&gt;

&lt;p&gt;The Solidity hashing library receives document-entry fields and does not parse
or canonicalize JSON, XML, PDF, images, filenames, or media types. A caller can
submit a hash while falsely claiming that a profile was followed. Consumers
must reproduce normalization and entry derivation off-chain.&lt;/p&gt;

&lt;h3 id=&quot;document-availability-and-privacy&quot;&gt;Document Availability and Privacy&lt;/h3&gt;

&lt;p&gt;An anchored hash does not make its preimage available. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadataURI&lt;/code&gt; can become
unavailable, change content, or expose sensitive information. Empty URIs are
permitted. Applications should use durable retrieval policies and must not
place personal, confidential, or legally restricted information directly in a
public URI.&lt;/p&gt;

&lt;h3 id=&quot;declarative-document-count&quot;&gt;Declarative Document Count&lt;/h3&gt;

&lt;p&gt;The anchoring contract cannot verify that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt; matches the committed
manifest. Consumers should count the reproduced entries rather than trusting
the stored value independently.&lt;/p&gt;

&lt;h3 id=&quot;authorization-and-slot-squatting&quot;&gt;Authorization and Slot Squatting&lt;/h3&gt;

&lt;p&gt;A caller with anchoring authority can occupy an unassigned slot. Implementations
should scope authorization appropriately or pre-assign principals for protected
slots. Recovery administrators can redirect legitimate authority and therefore
require strong operational controls.&lt;/p&gt;

&lt;h3 id=&quot;supersession-front-running&quot;&gt;Supersession Front-Running&lt;/h3&gt;

&lt;p&gt;An administrator attempting direct supersession of a contested slot can be
front-run by the current principal. Implementations supporting recovery should
use atomic principal reassignment before the legitimate principal supersedes the
active bundle.&lt;/p&gt;

&lt;h3 id=&quot;hash-and-encoding-assumptions&quot;&gt;Hash and Encoding Assumptions&lt;/h3&gt;

&lt;p&gt;The construction relies on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; collision resistance. Packed encoding is
used only for fixed-width fields. Implementations must not substitute
variable-length fields into the leaf or bundle encoding without introducing
unambiguous length encoding and a new schema identifier.&lt;/p&gt;

&lt;h3 id=&quot;filename-and-unicode-handling&quot;&gt;Filename and Unicode Handling&lt;/h3&gt;

&lt;p&gt;ASCII case folding does not provide Unicode case equivalence. NFC normalization
requires a conforming Unicode implementation. Different path or Unicode
handling will produce different filename hashes.&lt;/p&gt;

&lt;h3 id=&quot;no-authenticity-or-legal-effect-guarantee&quot;&gt;No Authenticity or Legal-Effect Guarantee&lt;/h3&gt;

&lt;p&gt;A reproducible bundle hash proves agreement on committed bytes, not that a
document is authentic, current, authorized, legally effective, or associated
with the claimed subject.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8326</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8326</guid>
      </item>
      
    
      
      
      <item>
        <title>Directional Transfer Domain Registry</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8327 - Directional Transfer Domain Registry&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8327-directional-transfer-domain-registry/28936&quot;&gt;https://ethereum-magicians.org/t/erc-8327-directional-transfer-domain-registry/28936&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines a token-agnostic registry
interface for querying directional
transfer-route permission between opaque domains by asset class. For an ordered
triple of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sourceDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;destinationDomain&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt;, the registry
reports whether that route is currently permitted and exposes the evidence
commitments and effective timestamp associated with its latest state.&lt;/p&gt;

&lt;p&gt;The core interface supports immediate route permission and revocation, state
retrieval, and batch queries. An optional extension supports delayed revocation
with explicit initiation, cancellation, lazy effectiveness, and finalization
semantics.&lt;/p&gt;

&lt;p&gt;This ERC does not assign addresses to domains, derive asset classes, validate
evidence, or enforce token transfers. A token or transfer controller that relies
on a route decision must resolve the applicable domains and asset class, query
the registry, and enforce the result within its transfer path.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Transfer restrictions are commonly expressed in token-local or address-level
logic. That model is appropriate when eligibility depends on a particular
holder, balance, token, or transaction amount. It does not provide a common
lookup surface for policies that apply to transfers between logical domains
across multiple tokens sharing an asset classification.&lt;/p&gt;

&lt;p&gt;A domain can represent a jurisdiction, regulated venue, enterprise network,
game economy, decentralized autonomous organization (DAO) treasury boundary,
or another application-defined context.
Transfer compatibility between such domains is often directional: permission
from domain A to domain B does not imply permission from B to A. The same route
can also differ by asset class.&lt;/p&gt;

&lt;p&gt;Without a shared interface, each token or controller embeds its own route table
or integrates with a proprietary registry. This duplicates policy state and
requires integrations to understand implementation-specific query methods.&lt;/p&gt;

&lt;p&gt;This ERC standardizes the narrow external question:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Is the route from this source domain to this destination domain currently
permitted for this asset class?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It deliberately does not answer whether a complete transfer can succeed.
Balances, holder eligibility, freezes, sanctions, settlement conditions, and
token-specific rules remain separate checks.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;definitions&quot;&gt;Definitions&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;domain&lt;/strong&gt; is an opaque, nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; identifier for an
application-defined logical boundary.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;asset class&lt;/strong&gt; is an opaque, nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; identifier for a category of
assets to which one route policy applies.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;route&lt;/strong&gt; is the ordered triple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(sourceDomain, destinationDomain,
assetClass)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;registrar&lt;/strong&gt; is an address authorized by the implementation to modify route
state.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;evidence hash&lt;/strong&gt; is a nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; commitment to application-defined
material supporting a route lifecycle action.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;grace period&lt;/strong&gt; is an implementation-defined delay between initiation and
effectiveness of a graceful revocation.&lt;/p&gt;

&lt;h3 id=&quot;core-interface&quot;&gt;Core Interface&lt;/h3&gt;

&lt;p&gt;A compliant registry MUST implement:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ITransferDomainRegistry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Route&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permitted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permissionEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RouteSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permissionEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RouteRevoked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isRoutePermitted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRoute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Route&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setRoute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permissionEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revokeRoute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isRoutePermittedBatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClasses&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permitted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;route-direction-and-scope&quot;&gt;Route Direction and Scope&lt;/h3&gt;

&lt;p&gt;Routes MUST be directional. A permitted route &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A, B, C)&lt;/code&gt; MUST NOT imply that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(B, A, C)&lt;/code&gt; is permitted. Bidirectional permission requires two independently
permitted routes.&lt;/p&gt;

&lt;p&gt;Routes MUST also be asset-class scoped. A permitted route &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A, B, C)&lt;/code&gt; MUST NOT
imply permission for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A, B, D)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The registry MUST treat each route triple independently.&lt;/p&gt;

&lt;h3 id=&quot;route-queries&quot;&gt;Route Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted&lt;/code&gt; MUST return the current permission state for the exact route
triple. It MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; for a route that has never been permitted, has
been revoked immediately, or has reached the effective time of a graceful
revocation.&lt;/p&gt;

&lt;p&gt;For a given block, the result MUST be deterministic and MUST NOT depend on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.origin&lt;/code&gt;, or caller-specific state.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRoute&lt;/code&gt; MUST return the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Route&lt;/code&gt; representation for the exact triple.
For an unknown route, it MUST return the default record in which every field is
zero.&lt;/p&gt;

&lt;p&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; is the time at which the current
permission state became effective. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; is nonzero, it is the time at which the latest revocation became
effective. An unknown route has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt == 0&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;setting-a-route&quot;&gt;Setting a Route&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; MUST be restricted to authorized registrars. It MUST reject a zero
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sourceDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;destinationDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt;, or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;store the supplied &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteSet&lt;/code&gt; with the stored values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; for an already permitted or previously revoked route is
allowed. The new call replaces the route’s current state and evidence fields;
prior lifecycle actions remain discoverable through events.&lt;/p&gt;

&lt;p&gt;An implementation MUST reject the call if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; cannot be
represented as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;immediate-revocation&quot;&gt;Immediate Revocation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt; MUST be restricted to authorized registrars. It MUST reject a
zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sourceDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;destinationDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt;, or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt; MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;preserve the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;store the supplied &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; with the stored values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For an authorized caller supplying valid nonzero arguments, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt; MUST
NOT revert solely because the route was unknown or already revoked. Revoking an
unknown route creates a non-permitted route state with zero permission evidence
and the supplied revocation evidence. Repeated revocation replaces the latest
revocation timestamp and evidence and emits a new event.&lt;/p&gt;

&lt;p&gt;An implementation MUST reject the call if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; cannot be
represented as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;evidence-semantics&quot;&gt;Evidence Semantics&lt;/h3&gt;

&lt;p&gt;All evidence hashes accepted by this ERC MUST be nonzero. The registry treats
them as opaque commitments and does not validate their preimages, hashing
scheme, authority, correctness, or availability.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt; represents the evidence supplied for the current
permission state. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt; represents the evidence supplied for
the current revocation state and MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; while the route is
permitted.&lt;/p&gt;

&lt;p&gt;Route state contains only the latest evidence fields. Consumers reconstructing
the complete lifecycle MUST index the route events.&lt;/p&gt;

&lt;h3 id=&quot;batch-queries&quot;&gt;Batch Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermittedBatch&lt;/code&gt; MUST revert when its three arrays have different
lengths. Otherwise, it MUST return an array of the same length in which output
element &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; equals:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;isRoutePermitted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;sourceDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;destinationDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;assetClasses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Implementations MAY impose a documented maximum batch size. Consumers calling
the batch function from state-changing execution SHOULD bound the input length.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-extension&quot;&gt;Graceful Revocation Extension&lt;/h3&gt;

&lt;p&gt;Graceful revocation is OPTIONAL. A registry implementing it MUST implement both
the core interface and the following extension:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IGracefulRouteRevocation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Revocation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finalized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RouteRevocationInitiated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RouteRevocationCancelled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancellationEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRevocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Revocation&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiateRevocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancelRevocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancellationEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finalizeRevocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The grace-period duration and its configuration mechanism are implementation
defined. The implementation MUST document that policy. Only the resulting
timestamps and state transitions are standardized.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-initiation&quot;&gt;Graceful Revocation Initiation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiateRevocation&lt;/code&gt; MUST be restricted to authorized registrars. It MUST
reject a zero route identifier or zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It MUST revert unless &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted&lt;/code&gt; currently returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for the route
and no graceful revocation is pending.&lt;/p&gt;

&lt;p&gt;On success, it MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiatedAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; to a representable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt; value strictly later than
 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiatedAt&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;store the supplied &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finalized&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevocationInitiated&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The route MUST remain permitted while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;lt; effectiveAt&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;lazy-effectiveness&quot;&gt;Lazy Effectiveness&lt;/h3&gt;

&lt;p&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;gt;= effectiveAt&lt;/code&gt; for a pending graceful revocation,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; without requiring a finalization
transaction.&lt;/p&gt;

&lt;p&gt;During that interval, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRoute&lt;/code&gt; MUST return an effective route representation
with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted == false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; equal to the graceful revocation’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt; equal to the graceful revocation evidence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stored revocation remains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending&lt;/code&gt; until finalized, but the route is
already non-permitted. Therefore, consumers MUST NOT infer route permission
from whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; has been emitted.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-cancellation&quot;&gt;Graceful Revocation Cancellation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cancelRevocation&lt;/code&gt; MUST be restricted to authorized registrars. It MUST reject
a zero route identifier or zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cancellationEvidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It MUST revert unless a revocation is pending and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;lt; effectiveAt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, it MUST clear the revocation state and emit
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevocationCancelled&lt;/code&gt;. The route remains permitted. The cancellation
evidence is emitted but is not retained in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Revocation&lt;/code&gt; struct; consumers
requiring it MUST index the event.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-finalization&quot;&gt;Graceful Revocation Finalization&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finalizeRevocation&lt;/code&gt; MUST reject a zero route identifier. It MUST revert unless
a revocation is pending and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;gt;= effectiveAt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, it MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finalized&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;persist the route as non-permitted;&lt;/li&gt;
  &lt;li&gt;set the route’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; to the graceful revocation effective time;&lt;/li&gt;
  &lt;li&gt;store the graceful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt; on the route; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; exactly once for that graceful revocation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finalization MAY be permissionless because route effectiveness does not depend
on it. Repeated or nonexistent finalization MUST NOT emit a duplicate
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;The finalized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Revocation&lt;/code&gt; record MUST remain queryable until another route
lifecycle action clears it.&lt;/p&gt;

&lt;h3 id=&quot;interaction-with-core-lifecycle-functions&quot;&gt;Interaction With Core Lifecycle Functions&lt;/h3&gt;

&lt;p&gt;In a registry implementing the graceful extension, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; MUST clear any
pending or finalized graceful-revocation record before installing the new
permission state.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt; MUST clear any pending or finalized graceful-revocation record
before installing the immediate revocation state.&lt;/p&gt;

&lt;p&gt;These actions do not emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevocationCancelled&lt;/code&gt;. Their respective
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteSet&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; event records the state transition.&lt;/p&gt;

&lt;h3 id=&quot;domain-and-asset-class-identification&quot;&gt;Domain and Asset-Class Identification&lt;/h3&gt;

&lt;p&gt;This ERC does not map accounts or tokens to domains and does not define domain
or asset-class taxonomies. Applications MUST document how they derive each
identifier supplied to the registry.&lt;/p&gt;

&lt;p&gt;Identifiers SHOULD be domain separated by an application or registry
namespace. The same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; value in two independent registries MUST NOT be
assumed to have the same meaning without an explicit coordination agreement.&lt;/p&gt;

&lt;p&gt;An asset class MAY represent a regulatory category, asset type, product class,
or a single asset when per-asset routing is required. The mapping from an
individual token or asset identifier to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt; is application defined.&lt;/p&gt;

&lt;h3 id=&quot;authorization&quot;&gt;Authorization&lt;/h3&gt;

&lt;p&gt;Registrar authorization is implementation defined. A registry MAY use
ownership, role-based access control, governance, signatures, or another
documented mechanism.&lt;/p&gt;

&lt;p&gt;Whatever mechanism is selected, unauthorized callers MUST NOT be able to call
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiateRevocation&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cancelRevocation&lt;/code&gt;
successfully.&lt;/p&gt;

&lt;h3 id=&quot;interface-detection&quot;&gt;Interface Detection&lt;/h3&gt;

&lt;p&gt;Compliant registries MUST implement &lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(ITransferDomainRegistry).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Registries implementing graceful revocation MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IGracefulRouteRevocation).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ERC-165 indicates interface support only. It does not prove that route data is
correct, that the registry is governed appropriately, or that a token or
controller enforces registry decisions.&lt;/p&gt;

&lt;h3 id=&quot;consumer-enforcement&quot;&gt;Consumer Enforcement&lt;/h3&gt;

&lt;p&gt;A consumer enforcing a route decision SHOULD perform the following within the
same transaction as the governed transfer:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Resolve the sender and receiver to the applicable source and destination
  domains using an authoritative application-defined mechanism.&lt;/li&gt;
  &lt;li&gt;Resolve the token or asset to the applicable asset class.&lt;/li&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted(sourceDomain, destinationDomain, assetClass)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Reject the transfer when the result is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Apply all independent token, identity, balance, freeze, sanctions, and
  settlement checks required by the application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Checking route permission off-chain before submitting a later transfer does not
provide atomic enforcement because route state can change between the check and
execution.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;why-directional-routes&quot;&gt;Why Directional Routes?&lt;/h3&gt;

&lt;p&gt;Compatibility can be asymmetric. A domain may allow outbound transfers to
another domain without accepting inbound transfers from it. Encoding each
direction separately avoids an unsafe assumption of reciprocity.&lt;/p&gt;

&lt;h3 id=&quot;why-opaque-domains&quot;&gt;Why Opaque Domains?&lt;/h3&gt;

&lt;p&gt;Standardizing one universal domain taxonomy would couple the interface to a
particular legal, organizational, or application model. Opaque identifiers let
independent systems use the same route interface while defining their own
meaning and resolution mechanism.&lt;/p&gt;

&lt;h3 id=&quot;why-scope-routes-by-asset-class&quot;&gt;Why Scope Routes by Asset Class?&lt;/h3&gt;

&lt;p&gt;The same pair of domains can permit one category of assets and prohibit
another. Asset-class scoping allows multiple assets governed by the same route
policy to share one entry without requiring per-token route storage.&lt;/p&gt;

&lt;h3 id=&quot;why-an-external-registry&quot;&gt;Why an External Registry?&lt;/h3&gt;

&lt;p&gt;An external registry allows multiple tokens and controllers to consult one
route-policy surface. It also separates route administration from token
implementation and avoids requiring every supported token standard to adopt
the same storage model.&lt;/p&gt;

&lt;h3 id=&quot;why-isroutepermitted-instead-of-cantransfer&quot;&gt;Why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted&lt;/code&gt; Instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canTransfer&lt;/code&gt;?&lt;/h3&gt;

&lt;p&gt;The registry evaluates only the supplied route triple. A name such as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canTransfer&lt;/code&gt; would imply checks that the interface does not perform, including
balances, account eligibility, freezes, sanctions, and token-specific rules.&lt;/p&gt;

&lt;h3 id=&quot;why-require-nonzero-evidence-commitments&quot;&gt;Why Require Nonzero Evidence Commitments?&lt;/h3&gt;

&lt;p&gt;A zero hash is ambiguous between absent evidence and a meaningful commitment.
Requiring a nonzero value makes absence explicit at the application layer and
prevents route records from silently appearing documented when no commitment
was supplied.&lt;/p&gt;

&lt;h3 id=&quot;why-is-immediate-revocation-idempotent-over-route-existence&quot;&gt;Why Is Immediate Revocation Idempotent Over Route Existence?&lt;/h3&gt;

&lt;p&gt;An authorized registrar should be able to establish a route as non-permitted
without first proving that it was previously enabled. This supports defensive
revocation and repeated emergency actions while retaining each action in the
event history.&lt;/p&gt;

&lt;h3 id=&quot;why-graceful-revocation-as-an-extension&quot;&gt;Why Graceful Revocation as an Extension?&lt;/h3&gt;

&lt;p&gt;Some systems need immediate emergency closure. Others have in-flight settlement
or notice obligations that require a future effective time. Keeping delayed
revocation optional preserves a small core interface while standardizing the
additional lifecycle only for deployments that need it.&lt;/p&gt;

&lt;h3 id=&quot;why-lazy-effectiveness&quot;&gt;Why Lazy Effectiveness?&lt;/h3&gt;

&lt;p&gt;If route closure depended on a later finalization transaction, a missing or
censored transaction could leave the route permitted indefinitely. Lazy
effectiveness makes the announced timestamp authoritative. Finalization exists
to persist state and emit the terminal event, not to activate the revocation.&lt;/p&gt;

&lt;h3 id=&quot;why-keep-grace-period-configuration-implementation-defined&quot;&gt;Why Keep Grace-Period Configuration Implementation Defined?&lt;/h3&gt;

&lt;p&gt;Appropriate delay depends on the applicable settlement cycle and policy. The
interface exposes the resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; timestamp, which consumers need
for interoperability, without prescribing one configuration mechanism or
duration.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-3643&quot;&gt;ERC-3643&lt;/a&gt; defines a regulated-token architecture with identity
registries, compliance modules, and token lifecycle functions. This ERC does
not define holder eligibility or token behavior; it provides one route-policy
input that such systems may optionally consume.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7943&quot;&gt;ERC-7943&lt;/a&gt; defines a universal real-world asset (RWA) token
interface including transfer eligibility, freezing, and forced transfer
behavior. This ERC is an external registry keyed by domains and asset classes
rather than a token behavior interface.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This ERC introduces new interfaces and does not modify existing token
standards. Existing &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt;,
&lt;a href=&quot;/EIPS/eip-1155&quot;&gt;ERC-1155&lt;/a&gt;, &lt;a href=&quot;/EIPS/eip-3643&quot;&gt;ERC-3643&lt;/a&gt;,
&lt;a href=&quot;/EIPS/eip-7943&quot;&gt;ERC-7943&lt;/a&gt;, and custom tokens remain unaffected unless their
transfer path is explicitly integrated with a registry.&lt;/p&gt;

&lt;p&gt;The registry does not require a token to expose a new interface. A token,
compliance module, transfer controller, bridge, or settlement contract can call
the registry as an external dependency.&lt;/p&gt;

&lt;p&gt;Implementations that do not need delayed revocation implement only
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITransferDomainRegistry&lt;/code&gt;. Implementations that need delayed revocation
additionally implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IGracefulRouteRevocation&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;directional independence of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A, B, C)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(B, A, C)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;asset-class independence for the same domain pair;&lt;/li&gt;
  &lt;li&gt;caller-independent route queries;&lt;/li&gt;
  &lt;li&gt;default false and zero state for unknown routes;&lt;/li&gt;
  &lt;li&gt;nonzero validation for route identifiers and every evidence field;&lt;/li&gt;
  &lt;li&gt;setting, repeated setting, immediate revocation, repeated revocation, and
 re-enablement;&lt;/li&gt;
  &lt;li&gt;immediate revocation of an unknown route;&lt;/li&gt;
  &lt;li&gt;route evidence retrieval and event history;&lt;/li&gt;
  &lt;li&gt;batch output equivalence with individual queries;&lt;/li&gt;
  &lt;li&gt;mismatched batch lengths and implementation batch limits;&lt;/li&gt;
  &lt;li&gt;graceful initiation only for a currently permitted route;&lt;/li&gt;
  &lt;li&gt;permission before, and non-permission at, graceful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;lazy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRoute&lt;/code&gt; behavior before finalization;&lt;/li&gt;
  &lt;li&gt;cancellation before expiry and rejection at or after expiry;&lt;/li&gt;
  &lt;li&gt;finalization persistence and duplicate-event prevention;&lt;/li&gt;
  &lt;li&gt;immediate revocation and re-enablement while graceful state exists;&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection; and&lt;/li&gt;
  &lt;li&gt;unauthorized lifecycle calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;A Solidity reference implementation includes immediate and graceful registry
contracts, a canonical route-key library, unit and fuzz tests, Medusa property
tests, deployment scripts, and an independent audit. These materials are linked
from the official discussion thread.&lt;/p&gt;

&lt;p&gt;The reference implementation uses role-based registrar authorization, a
deployment-time fixed grace period, a maximum batch size of 256, and:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;as its internal route key. Those storage and administration choices are not
required for conforming implementations.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;no-enforcement-guarantee&quot;&gt;No Enforcement Guarantee&lt;/h3&gt;

&lt;p&gt;The registry is advisory. A token or controller that does not query and enforce
the result can transfer regardless of route state. ERC-165 support by either
contract does not prove that enforcement occurs.&lt;/p&gt;

&lt;h3 id=&quot;domain-and-asset-class-resolution&quot;&gt;Domain and Asset-Class Resolution&lt;/h3&gt;

&lt;p&gt;The registry evaluates caller-supplied identifiers. Incorrect, stale, or
malicious resolution of an address or token to a domain or asset class can
bypass the intended policy even when the registry itself is correct. Consumers
must secure and document their resolution mechanism.&lt;/p&gt;

&lt;h3 id=&quot;registry-and-registrar-trust&quot;&gt;Registry and Registrar Trust&lt;/h3&gt;

&lt;p&gt;A malicious or compromised registrar can permit prohibited routes, revoke
valid routes, replace evidence commitments, or repeatedly change state. Users
must evaluate the registry’s authorization, governance, upgrade, and key
management policies.&lt;/p&gt;

&lt;h3 id=&quot;evidence-limitations&quot;&gt;Evidence Limitations&lt;/h3&gt;

&lt;p&gt;An evidence hash proves only commitment to unknown bytes if the preimage is
available. It does not establish authenticity, legal effect, correctness,
authority, or continued availability. Consumers relying on evidence must obtain
and verify the preimage under an agreed hashing and document scheme.&lt;/p&gt;

&lt;h3 id=&quot;transaction-atomicity-and-races&quot;&gt;Transaction Atomicity and Races&lt;/h3&gt;

&lt;p&gt;An off-chain route query can become stale before a transfer executes. Enforcing
consumers should query the registry and complete or reject the transfer within
the same transaction.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-risk&quot;&gt;Graceful Revocation Risk&lt;/h3&gt;

&lt;p&gt;The route remains permitted before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt;, so the grace period creates a
known window in which transfers can continue. Applications must choose a delay
appropriate to their threat and settlement models. Emergency closure should
use immediate revocation.&lt;/p&gt;

&lt;p&gt;An authorized registrar can clear graceful state by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt;. Consumers requiring governance constraints around reinstatement
must enforce them in the registry’s authorization policy.&lt;/p&gt;

&lt;h3 id=&quot;lazy-revocation-and-event-only-indexers&quot;&gt;Lazy Revocation and Event-Only Indexers&lt;/h3&gt;

&lt;p&gt;A graceful revocation becomes effective without a transaction at
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt;. An indexer that waits only for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; can report stale
permission until finalization. Consumers must evaluate timestamps or call the
view interface.&lt;/p&gt;

&lt;h3 id=&quot;batch-gas-consumption&quot;&gt;Batch Gas Consumption&lt;/h3&gt;

&lt;p&gt;Although batch lookup is a view function, another contract can invoke it from a
state-changing transaction. Unbounded arrays can consume excessive gas or make
the calling operation unavailable. Implementations and callers should apply
appropriate limits.&lt;/p&gt;

&lt;h3 id=&quot;identifier-collisions-and-cross-registry-meaning&quot;&gt;Identifier Collisions and Cross-Registry Meaning&lt;/h3&gt;

&lt;p&gt;Opaque identifiers have no global namespace. Two applications or registries
can assign the same value to different domains or asset classes. Consumers must
scope interpretation to the selected registry and its documented namespace.&lt;/p&gt;

&lt;h3 id=&quot;timestamp-dependence&quot;&gt;Timestamp Dependence&lt;/h3&gt;

&lt;p&gt;Graceful revocation depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;. Block producers can influence
timestamps within protocol bounds. Applications requiring exact wall-clock
cutoffs must account for this uncertainty.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8327</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8327</guid>
      </item>
      
    
      
      
      <item>
        <title>Subject-Linked Compliance Event Log</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8328 - Subject-Linked Compliance Event Log&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8328-subject-linked-compliance-event-log/28937&quot;&gt;https://ethereum-magicians.org/t/erc-8328-subject-linked-compliance-event-log/28937&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines an append-only interface for
subject-linked compliance event
records. Each record includes a subject, event type, outcome, technical actor,
claimed authority, involved parties, evidence commitment, optional evidence
location, versioned payload profile, operation reference, occurrence time, and
recording time.&lt;/p&gt;

&lt;p&gt;Events are indexed per subject and by event type. Corrections are recorded as
new events linked to earlier records. A forward pointer on the corrected record
prevents correction forks and allows consumers to resolve the terminal event in
a correction chain.&lt;/p&gt;

&lt;p&gt;This ERC is a reporting interface. It does not define compliance policy,
identity verification, transfer restrictions, legal authority, or regulatory
compliance. Stored records are attributable assertions, not proof that the
reported action occurred or was lawful.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Compliance-relevant lifecycle actions are currently represented through
application-specific events, token-local state changes, generic attestations,
and off-chain databases. This fragmentation makes it difficult for contracts,
indexers, auditors, and reporting systems to query comparable records across
implementations.&lt;/p&gt;

&lt;p&gt;Existing token and compliance standards primarily define token behavior,
holder eligibility, transfer validation, or entity classification. Those
capabilities do not provide a common stored record for subject-level lifecycle
actions such as issuance, redemption, freezing, know-your-customer (KYC)
status changes, regulatory holds, policy changes, and forced transfers.&lt;/p&gt;

&lt;p&gt;A shared event-log interface provides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;one query surface for records attached to an application-defined subject;&lt;/li&gt;
  &lt;li&gt;explicit separation between the recorder and the claimed authority;&lt;/li&gt;
  &lt;li&gt;structured party roles rather than untyped address arrays;&lt;/li&gt;
  &lt;li&gt;evidence commitments and optional retrieval references;&lt;/li&gt;
  &lt;li&gt;versioned payload profiles for interoperable event-specific data;&lt;/li&gt;
  &lt;li&gt;per-type indexing without scanning an entire subject history; and&lt;/li&gt;
  &lt;li&gt;append-only, fork-free correction provenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The log can be called by a token, compliance module, governance executor,
multisig, or other authorized recorder. It does not require any particular
token standard or enforcement architecture.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;definitions&quot;&gt;Definitions&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;subject&lt;/strong&gt; is an application-defined entity identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; and,
optionally, contextualized by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectType&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;compliance event&lt;/strong&gt; is a stored assertion about a compliance-relevant action
or state transition concerning a subject.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;actor&lt;/strong&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; at the time &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; is called. It identifies
the technical recorder, not necessarily the human decision-maker or legal
authority.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;authority&lt;/strong&gt; is the recorder’s claimed legal, regulatory, contractual, or
governance basis for the event. The claim is not verified by the log.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;party&lt;/strong&gt; is an EVM address associated with an explicit role in the event.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;payload profile&lt;/strong&gt; is a versioned schema declaring how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload&lt;/code&gt; is encoded.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;correction chain&lt;/strong&gt; is a linear sequence of events linked by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;terminal event&lt;/strong&gt; is an event whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; equals
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;sentinel-values&quot;&gt;Sentinel Values&lt;/h3&gt;

&lt;p&gt;Implementations MUST use:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTED_BY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTION&lt;/code&gt; indicates that an event does not correct an earlier event.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt; indicates that an event has no successor correction. Event
index zero is safe for this sentinel because a correction’s index is always
greater than the index it corrects and therefore can never be zero.&lt;/p&gt;

&lt;h3 id=&quot;core-interface&quot;&gt;Core Interface&lt;/h3&gt;

&lt;p&gt;A compliant log MUST implement:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IComplianceEventLog&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Party&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComplianceEvent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authority&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Party&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payloadProfileId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operationRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;occurredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctedByIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComplianceEventRecorded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authority&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;occurredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authority&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Party&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payloadProfileId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operationRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;occurredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ComplianceEvent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentEventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isEventCurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventCountByType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventByTypeAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ordinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastRecordedEventByType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;recording-semantics&quot;&gt;Recording Semantics&lt;/h3&gt;

&lt;p&gt;Event indices MUST be zero-based and scoped per &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;. The returned
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventIndex&lt;/code&gt; MUST equal the subject’s event count immediately before the new
event is appended.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; MUST be restricted to authorized recorders. The authorization
mechanism is implementation defined and MUST be documented.&lt;/p&gt;

&lt;p&gt;For every accepted event, the implementation MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;store every supplied field without changing its value, except as explicitly
specified by this ERC;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;actor&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordedAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;append the event index to the subject and event-type index;&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComplianceEventRecorded&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;return the new event index.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The implementation MUST reject the call if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; cannot be
represented as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceHash&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceURI&lt;/code&gt; MAY be empty when the
evidence location is private, unavailable on-chain, or exchanged out of band.
An empty URI does not weaken the requirement for a nonzero commitment.&lt;/p&gt;

&lt;p&gt;The parties array MUST contain no more than 10 entries. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload&lt;/code&gt; MUST contain
no more than 2048 bytes. Empty party arrays and empty payloads are allowed.&lt;/p&gt;

&lt;p&gt;This ERC does not require nonzero values for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectType&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventType&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;outcome&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authority&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;operationRef&lt;/code&gt;, party addresses, party
roles, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payloadProfileId&lt;/code&gt;. Applications requiring stricter semantics MUST
enforce and document them before calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;temporal-semantics&quot;&gt;Temporal Semantics&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt&lt;/code&gt; represents when the reported action occurred. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordedAt&lt;/code&gt;
represents when the record was appended on-chain.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; MUST revert when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt &amp;gt; block.timestamp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Implementations SHOULD impose and document a maximum backdating interval.
Different deployments can require different intervals, so the duration is not
standardized by this ERC.&lt;/p&gt;

&lt;p&gt;The log does not independently verify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt&lt;/code&gt;. It is an assertion by the
recorder.&lt;/p&gt;

&lt;h3 id=&quot;append-only-semantics&quot;&gt;Append-Only Semantics&lt;/h3&gt;

&lt;p&gt;Once recorded, every event field MUST remain immutable except
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt;. Events MUST NOT be deleted.&lt;/p&gt;

&lt;p&gt;Updating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; is permitted only when accepting a valid correction
under the correction rules below.&lt;/p&gt;

&lt;h3 id=&quot;correction-semantics&quot;&gt;Correction Semantics&lt;/h3&gt;

&lt;p&gt;An original or non-correction event MUST use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTION&lt;/code&gt; and MUST NOT use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_CORRECTION&lt;/code&gt;, which is defined in the Event Types section below:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;correctsIndex = NO_CORRECTION
eventType != EVT_CORRECTION
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A correction event MUST use:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;correctsIndex = index of the corrected event
eventType = EVT_CORRECTION
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For a correction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; to identify an earlier event under the same
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;require the target event’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to equal
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;authorize the correction under the implementation’s documented correction
policy;&lt;/li&gt;
  &lt;li&gt;set the target’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to the new correction event index; and&lt;/li&gt;
  &lt;li&gt;append the correction as a new event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The correction policy MUST NOT permit an ordinary recorder to correct another
actor’s event merely because both addresses can record events. It MAY authorize
the original actor, a designated corrector, or an administrator. The policy
MUST be documented.&lt;/p&gt;

&lt;p&gt;Each event can be corrected at most once, preventing forks. A correction event
can itself be corrected later, producing a linear chain.&lt;/p&gt;

&lt;p&gt;The correcting record does not rewrite the original event’s event type or
payload. Recorders MUST place the corrected assertion in the new event’s fields
or an application-defined correction payload. Consumers MUST interpret the
terminal event under the applicable profile and application policy.&lt;/p&gt;

&lt;h3 id=&quot;current-state-queries&quot;&gt;Current-State Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentEventIndex&lt;/code&gt; MUST revert when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventIndex &amp;gt;= eventCount(subjectId)&lt;/code&gt;.
Otherwise, it MUST follow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; until reaching
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt; and return the terminal event index. Calling it on a terminal
event MUST return the supplied index.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isEventCurrent&lt;/code&gt; MUST revert when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventIndex &amp;gt;= eventCount(subjectId)&lt;/code&gt; and
otherwise return whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex == NO_CORRECTED_BY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because corrections always point to earlier events and each event has at most
one successor, conforming correction chains cannot contain cycles or branches.&lt;/p&gt;

&lt;h3 id=&quot;event-retrieval-and-counting&quot;&gt;Event Retrieval and Counting&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getEvent&lt;/code&gt; MUST return the complete stored event and MUST revert when
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventIndex &amp;gt;= eventCount(subjectId)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventCount&lt;/code&gt; MUST return the number of events stored under a subject.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventCountByType&lt;/code&gt; MUST return the number of events recorded with the exact
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventType&lt;/code&gt; under a subject.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventByTypeAt&lt;/code&gt; MUST return the event index at the specified zero-based ordinal
and MUST revert when the ordinal is outside the type-specific index.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastRecordedEventByType&lt;/code&gt; MUST return the greatest event index recorded with
the exact event type and MUST revert when no matching event exists.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastRecordedEventByType&lt;/code&gt; describes recording order. It does not select the
event with the greatest &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt&lt;/code&gt; and does not resolve correction chains.&lt;/p&gt;

&lt;p&gt;Correction events are indexed under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_CORRECTION&lt;/code&gt;, not under the event type
they correct. Consumers resolving an earlier event MUST use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentEventIndex&lt;/code&gt; rather than assuming the last event of the original type is
its current state.&lt;/p&gt;

&lt;h3 id=&quot;subject-identifiers&quot;&gt;Subject Identifiers&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectType&lt;/code&gt; are opaque to the log. Applications SHOULD use a
documented, domain-separated derivation and MUST NOT assume that equal subject
identifiers from independent logs have equal meaning without an explicit
coordination agreement.&lt;/p&gt;

&lt;p&gt;The following subject-type identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUBJECT_TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:SUBJECT_TYPE:TOKEN&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUBJECT_ADDRESS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:SUBJECT_TYPE:ADDRESS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUBJECT_ASSET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:SUBJECT_TYPE:ASSET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUBJECT_CASE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:SUBJECT_TYPE:CASE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Applications MAY define custom subject types using a documented namespace and
version.&lt;/p&gt;

&lt;h3 id=&quot;event-types&quot;&gt;Event Types&lt;/h3&gt;

&lt;p&gt;The following event-type identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_ISSUANCE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:ISSUANCE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_TRANSFER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:TRANSFER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_REDEMPTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:REDEMPTION:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_FREEZE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:FREEZE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_UNFREEZE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:UNFREEZE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_FORCED_TRANSFER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:FORCED_TRANSFER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_KYC_APPROVED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:KYC_APPROVED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_KYC_REVOKED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:KYC_REVOKED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_KYC_UPDATED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:KYC_UPDATED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_REGULATORY_HOLD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:REGULATORY_HOLD:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_HOLD_RELEASED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:HOLD_RELEASED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_ALLOWLIST_ADDED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:ALLOWLIST_ADDED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_ALLOWLIST_REMOVED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:ALLOWLIST_REMOVED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_POLICY_CHANGE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:POLICY_CHANGE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_CORRECTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:CORRECTION:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_TRANSFER&lt;/code&gt; is intended for compliance-significant transfer records, not as
a replacement for a token’s ordinary transfer event. Applications SHOULD avoid
duplicating every routine token transfer unless the additional compliance
record is required by their reporting policy.&lt;/p&gt;

&lt;p&gt;Custom event types SHOULD use a domain-separated namespace and explicit
version.&lt;/p&gt;

&lt;h3 id=&quot;party-roles&quot;&gt;Party Roles&lt;/h3&gt;

&lt;p&gt;The following party-role identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_SENDER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:SENDER&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_RECEIVER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:RECEIVER&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_TARGET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:TARGET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_BENEFICIARY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:BENEFICIARY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_CONTROLLER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:CONTROLLER&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_SUBJECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:SUBJECT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Custom party roles SHOULD use a documented namespace and version.&lt;/p&gt;

&lt;p&gt;The base &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Party&lt;/code&gt; type contains an EVM address. It cannot carry an arbitrary
hashed identity without changing the interface. Applications needing private
or non-address party identifiers require a separate extension or SHOULD omit
those parties from the public record.&lt;/p&gt;

&lt;h3 id=&quot;outcomes&quot;&gt;Outcomes&lt;/h3&gt;

&lt;p&gt;The following outcome identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_APPROVED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:APPROVED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_DENIED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:DENIED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_PENDING&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:PENDING&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_EXECUTED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:EXECUTED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_EXPIRED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:EXPIRED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_REVOKED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:REVOKED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This ERC does not define or enforce an event-type and outcome compatibility
matrix. Applications MAY constrain combinations before recording. Consumers
MUST NOT infer that a combination was validated merely because the log accepted
it.&lt;/p&gt;

&lt;h3 id=&quot;authority-identifiers&quot;&gt;Authority Identifiers&lt;/h3&gt;

&lt;p&gt;The following common authority identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AUTHORITY_INTERNAL_POLICY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:AUTHORITY:INTERNAL_POLICY:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AUTHORITY_COURT_ORDER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:AUTHORITY:COURT_ORDER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AUTHORITY_REGULATOR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:AUTHORITY:REGULATOR:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Custom authority identifiers SHOULD use a documented namespace and version.
The field records a claim and does not authenticate the named authority.&lt;/p&gt;

&lt;h3 id=&quot;payload-profiles&quot;&gt;Payload Profiles&lt;/h3&gt;

&lt;p&gt;The following payload-profile identifiers and ABI encodings are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAYLOAD_TRANSFER_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PAYLOAD:TRANSFER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// abi.encode(
//     address from,
//     address to,
//     uint256 amount,
//     bytes32 routeRef
// )
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAYLOAD_FREEZE_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PAYLOAD:FREEZE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// abi.encode(
//     address target,
//     uint256 amount,
//     uint64 expiresAt,
//     bytes32 reason
// )
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAYLOAD_KYC_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PAYLOAD:KYC:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// abi.encode(
//     address subject,
//     bytes32 jurisdiction,
//     bytes32 riskTier,
//     uint64 expiresAt
// )
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAYLOAD_FORCED_TRANSFER_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PAYLOAD:FORCED_TRANSFER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// abi.encode(
//     address from,
//     address to,
//     uint256 amount,
//     bytes32 legalBasis
// )
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A recorder declaring one of these profiles MUST encode the payload exactly as
specified. Consumers MUST inspect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payloadProfileId&lt;/code&gt; before decoding.&lt;/p&gt;

&lt;p&gt;The log is not required to decode payloads or validate compatibility between a
payload profile, event type, parties, and outcome. Consumers SHOULD reject a
malformed known profile. Unknown profile identifiers MUST be treated as opaque
bytes.&lt;/p&gt;

&lt;p&gt;Custom payload profiles SHOULD use a documented namespace and version and MUST
define an exact encoding.&lt;/p&gt;

&lt;h3 id=&quot;operation-references&quot;&gt;Operation References&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;operationRef&lt;/code&gt; is an application-defined correlation identifier linking the
record to an underlying action or workflow. It MAY be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; when no such
reference is available.&lt;/p&gt;

&lt;p&gt;A contract cannot access its transaction hash or final log index while
executing. Therefore, this ERC does not require a transaction-hash and log-index
derivation. Applications SHOULD compute a correlation identifier before the
underlying action and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; calls when both occur in one transaction.&lt;/p&gt;

&lt;p&gt;Recording an event in the same transaction as the underlying action provides
stronger linkage than recording it later, but the log still does not prove that
the record accurately describes that action.&lt;/p&gt;

&lt;h3 id=&quot;interface-detection&quot;&gt;Interface Detection&lt;/h3&gt;

&lt;p&gt;Compliant logs MUST implement &lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IComplianceEventLog).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ERC-165 indicates interface support only. It does not establish recorder
trustworthiness, evidence validity, authority, policy correctness, or legal
compliance.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;why-subject-linked-records&quot;&gt;Why Subject-Linked Records?&lt;/h3&gt;

&lt;p&gt;An address-only or token-only key would exclude projects, assets, cases,
policies, and application-defined entities. An opaque subject identifier allows
one query model while leaving identity and namespace semantics to the
application.&lt;/p&gt;

&lt;h3 id=&quot;why-separate-actor-and-authority&quot;&gt;Why Separate Actor and Authority?&lt;/h3&gt;

&lt;p&gt;The technical account recording an event and the claimed basis for the action
are different facts. A module can execute several actions under different
mandates, while multiple modules can act under the same mandate.&lt;/p&gt;

&lt;h3 id=&quot;why-structured-parties&quot;&gt;Why Structured Parties?&lt;/h3&gt;

&lt;p&gt;An untyped address list cannot distinguish a sender, receiver, target,
beneficiary, or controller. Explicit roles improve machine interpretation while
keeping the set extensible.&lt;/p&gt;

&lt;h3 id=&quot;why-require-an-evidence-commitment-but-permit-an-empty-uri&quot;&gt;Why Require an Evidence Commitment but Permit an Empty URI?&lt;/h3&gt;

&lt;p&gt;Every record should commit to the evidence representation used by the recorder,
but public retrieval can be inappropriate for confidential or regulated data.
A nonzero hash preserves the commitment while an optional URI permits private
distribution.&lt;/p&gt;

&lt;h3 id=&quot;why-versioned-payload-profiles&quot;&gt;Why Versioned Payload Profiles?&lt;/h3&gt;

&lt;p&gt;Opaque bytes without a declared schema prevent interoperable decoding.
Versioned profile identifiers let consumers recognize stable base encodings and
safely preserve unknown custom payloads.&lt;/p&gt;

&lt;h3 id=&quot;why-correction-events-instead-of-mutable-records&quot;&gt;Why Correction Events Instead of Mutable Records?&lt;/h3&gt;

&lt;p&gt;Replacing an event would erase the prior assertion. A correction chain retains
the full history and identifies the current terminal record. The forward
pointer and single-successor rule prevent competing corrections to the same
event.&lt;/p&gt;

&lt;h3 id=&quot;why-index-corrections-under-their-own-type&quot;&gt;Why Index Corrections Under Their Own Type?&lt;/h3&gt;

&lt;p&gt;A correction is a distinct lifecycle action. Indexing it under
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_CORRECTION&lt;/code&gt; preserves the original event-type history and lets consumers
query correction activity directly. Chain-resolution helpers provide current
state when needed.&lt;/p&gt;

&lt;h3 id=&quot;why-store-records-rather-than-emit-events-only&quot;&gt;Why Store Records Rather Than Emit Events Only?&lt;/h3&gt;

&lt;p&gt;EVM contracts cannot read historical logs. Storing records allows on-chain
consumers to retrieve event details, traverse correction chains, and iterate by
event type. Emitted events remain useful for off-chain indexing.&lt;/p&gt;

&lt;h3 id=&quot;why-keep-policy-validation-outside-the-log&quot;&gt;Why Keep Policy Validation Outside the Log?&lt;/h3&gt;

&lt;p&gt;The same event and outcome identifiers can be used under different legal and
application policies. The log standardizes representation and provenance, not
the rule engine deciding which combinations are valid.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; defines fungible-token transfers and balance changes.
This ERC records subject-linked lifecycle assertions and does not require each
record to correspond to an ERC-20 balance change.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-3643&quot;&gt;ERC-3643&lt;/a&gt; defines regulated-token behavior, identity
registries, compliance modules, and lifecycle operations. This ERC is a
reporting layer that such a system may call; it does not replace enforcement or
identity checks.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7943&quot;&gt;ERC-7943&lt;/a&gt; defines real-world asset (RWA) token behavior
including transfer eligibility, freezing, and forced transfers. This ERC
records attributed lifecycle assertions independently of any token interface.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This ERC introduces a new interface and does not modify existing token,
identity, attestation, or compliance standards.&lt;/p&gt;

&lt;p&gt;An existing token or compliance module can call a companion
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IComplianceEventLog&lt;/code&gt; without changing its base token interface. Systems that do
not integrate with the log are unaffected.&lt;/p&gt;

&lt;p&gt;The subject identifier is application defined, so adoption does not require a
particular asset registry or token standard.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;zero-based, per-subject event indexing;&lt;/li&gt;
  &lt;li&gt;subject isolation and event-type indexing;&lt;/li&gt;
  &lt;li&gt;actor assignment to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;recording-time assignment and future-event rejection;&lt;/li&gt;
  &lt;li&gt;the configured backdating policy;&lt;/li&gt;
  &lt;li&gt;rejection of zero evidence commitments;&lt;/li&gt;
  &lt;li&gt;empty and non-empty evidence URIs;&lt;/li&gt;
  &lt;li&gt;party and payload size boundaries;&lt;/li&gt;
  &lt;li&gt;original-event and correction-event guards;&lt;/li&gt;
  &lt;li&gt;correction target bounds and same-subject behavior;&lt;/li&gt;
  &lt;li&gt;original-actor, administrator, and unauthorized correction paths;&lt;/li&gt;
  &lt;li&gt;correction fork prevention and multi-step linear chains;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentEventIndex&lt;/code&gt; from original, intermediate, and terminal events;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isEventCurrent&lt;/code&gt; for corrected and terminal events;&lt;/li&gt;
  &lt;li&gt;invalid event and ordinal queries;&lt;/li&gt;
  &lt;li&gt;recording-order behavior of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastRecordedEventByType&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;correction indexing under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_CORRECTION&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;exact base payload-profile encodings;&lt;/li&gt;
  &lt;li&gt;opaque handling of unknown payload profiles;&lt;/li&gt;
  &lt;li&gt;acceptance of unconstrained event-type and outcome combinations; and&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;A Solidity reference implementation, constants library, unit tests, Medusa
property tests, and independent audit are linked from the official discussion
thread.&lt;/p&gt;

&lt;p&gt;The reference implementation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;uses recorder and administrator roles;&lt;/li&gt;
  &lt;li&gt;permits the original actor or an administrator with recorder authority to
correct an event;&lt;/li&gt;
  &lt;li&gt;limits party arrays to 10 entries;&lt;/li&gt;
  &lt;li&gt;limits payloads to 2048 bytes;&lt;/li&gt;
  &lt;li&gt;rejects events backdated by more than 30 days;&lt;/li&gt;
  &lt;li&gt;stores unknown payload profiles without decoding them; and&lt;/li&gt;
  &lt;li&gt;does not validate event-type and outcome combinations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Role design and the 30-day backdating window are reference deployment choices.
The size limits and externally observable interface behavior are requirements
of this ERC.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;recorder-trust&quot;&gt;Recorder Trust&lt;/h3&gt;

&lt;p&gt;The log proves that an authorized address recorded particular bytes. It does
not prove that the record is true. A compromised, malicious, or incorrectly
authorized recorder can submit false or misleading events.&lt;/p&gt;

&lt;h3 id=&quot;claimed-authority&quot;&gt;Claimed Authority&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authority&lt;/code&gt; is self-asserted. A recorder can claim a court order, regulator, or
internal policy that does not exist or does not authorize the action. Consumers
must verify authority evidence independently.&lt;/p&gt;

&lt;h3 id=&quot;underlying-action-verification&quot;&gt;Underlying Action Verification&lt;/h3&gt;

&lt;p&gt;A compliance event is not proof that the underlying issuance, transfer,
freeze, KYC decision, or other action occurred. Consumers requiring that proof
must verify the referenced operation and its relationship to the record.&lt;/p&gt;

&lt;h3 id=&quot;correction-authorization&quot;&gt;Correction Authorization&lt;/h3&gt;

&lt;p&gt;Fork prevention does not determine who is entitled to correct a record. A weak
correction policy can let one recorder supersede another recorder’s assertions.
Implementations must document and enforce correction authority.&lt;/p&gt;

&lt;h3 id=&quot;long-correction-chains&quot;&gt;Long Correction Chains&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentEventIndex&lt;/code&gt; traverses on-chain correction pointers. Although chains are
linear and acyclic, a long chain can consume substantial gas or make an on-chain
call impractical. Applications should avoid unnecessary repeated corrections
and may resolve long histories off-chain.&lt;/p&gt;

&lt;h3 id=&quot;backdating&quot;&gt;Backdating&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt&lt;/code&gt; is supplied by the recorder. Rejecting future timestamps prevents
one class of invalid input but does not establish historical accuracy. A
documented backdating limit reduces, but does not eliminate, fabricated history.&lt;/p&gt;

&lt;h3 id=&quot;privacy-and-data-protection&quot;&gt;Privacy and Data Protection&lt;/h3&gt;

&lt;p&gt;All event fields, dynamic payloads, party addresses, and URIs stored on a public
chain are permanently observable. Implementations must not place personal,
confidential, investigative, or legally restricted information on-chain merely
because the interface permits it.&lt;/p&gt;

&lt;p&gt;Public-chain deployments should use opaque or salted subject identifiers,
minimal party arrays, generalized outcomes, redacted payloads, and evidence
commitments whose preimages are distributed through appropriate access
controls. Hashing low-entropy personal data without a secret salt does not
provide meaningful privacy.&lt;/p&gt;

&lt;h3 id=&quot;evidence-availability-and-ambiguity&quot;&gt;Evidence Availability and Ambiguity&lt;/h3&gt;

&lt;p&gt;A nonzero evidence hash does not make evidence available or identify the
hashing and document scheme by itself. Implementations must document how
evidence commitments are derived and how authorized consumers obtain the
preimage.&lt;/p&gt;

&lt;h3 id=&quot;payload-confusion&quot;&gt;Payload Confusion&lt;/h3&gt;

&lt;p&gt;The log can store malformed known payloads and arbitrary unknown profiles. A
consumer that decodes without first checking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payloadProfileId&lt;/code&gt; can
misinterpret attacker-controlled bytes. Consumers must use profile-aware
decoding and reject malformed known profiles.&lt;/p&gt;

&lt;h3 id=&quot;event-type-and-outcome-confusion&quot;&gt;Event-Type and Outcome Confusion&lt;/h3&gt;

&lt;p&gt;The base log does not validate event-type and outcome combinations. Consumers
must not treat a stored combination as policy-approved unless the recorder’s
application enforces the applicable matrix.&lt;/p&gt;

&lt;h3 id=&quot;storage-growth-and-retrieval-costs&quot;&gt;Storage Growth and Retrieval Costs&lt;/h3&gt;

&lt;p&gt;The log is append-only and grows monotonically. Authorization, bounded dynamic
fields, reporting-frequency policy, and operational monitoring are necessary
to control storage costs and spam.&lt;/p&gt;

&lt;h3 id=&quot;event-and-storage-interpretation&quot;&gt;Event and Storage Interpretation&lt;/h3&gt;

&lt;p&gt;Off-chain indexers can reconstruct timelines from events, but on-chain
contracts cannot read historical logs. On-chain consumers must use storage
getters. Indexers should reconcile events with storage when resolving correction
chains and current state.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8328</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8328</guid>
      </item>
      
    
      
      
      <item>
        <title>Subject-Linked Impact Snapshot Log</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8329 - Subject-Linked Impact Snapshot Log&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8329-subject-linked-impact-snapshot-log/28938&quot;&gt;https://ethereum-magicians.org/t/erc-8329-subject-linked-impact-snapshot-log/28938&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines an append-only interface for
reporting quantitative impact
indicator snapshots against application-defined subjects. Each snapshot records
a signed value, decimal precision, unit, completed measurement period,
methodology commitment and location, reporter, recording time, and correction
provenance.&lt;/p&gt;

&lt;p&gt;The core interface supports per-subject storage, per-indicator indexing, exact
period lookup, and fork-free correction chains. Optional interfaces support
append-only endorsement or dispute attestations and future methodology
supersession with active and pending methodology discovery.&lt;/p&gt;

&lt;p&gt;This ERC standardizes representation and lifecycle behavior. It does not define
which indicators or methodologies are valid, verify reported measurements,
credential reporters or attestors, prevent overlapping claims, or provide an
impact score.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Impact measurements such as emissions, carbon offsets, renewable energy,
water treatment, employment, beneficiaries, biodiversity area, and diverted
waste are commonly distributed through reports and application-specific data
formats. On-chain systems lack a common interface for associating these values
with a subject, measurement period, unit, and methodology while preserving
later corrections.&lt;/p&gt;

&lt;p&gt;A single mutable value cannot distinguish a new reporting period from a
restatement of an earlier measurement. It also erases the prior assertion when
updated. Generic attestations can represent individual claims but do not by
themselves define per-indicator time-series indexing, exact-period uniqueness,
correction chains, or methodology transitions.&lt;/p&gt;

&lt;p&gt;This ERC provides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;subject-linked, period-bounded quantitative snapshots;&lt;/li&gt;
  &lt;li&gt;signed values with explicit decimals and units;&lt;/li&gt;
  &lt;li&gt;one original snapshot per exact subject, indicator, and period;&lt;/li&gt;
  &lt;li&gt;additive, fork-free corrections;&lt;/li&gt;
  &lt;li&gt;per-indicator iteration and exact-period current-state lookup;&lt;/li&gt;
  &lt;li&gt;required methodology commitments and retrieval references;&lt;/li&gt;
  &lt;li&gt;optional append-only endorsement and dispute attestations; and&lt;/li&gt;
  &lt;li&gt;optional active and scheduled methodology version discovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interfaces can be deployed independently of any token, registry, identity,
or accounting system.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;definitions&quot;&gt;Definitions&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;subject&lt;/strong&gt; is an application-defined entity identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;indicator&lt;/strong&gt; is an application-defined measured quantity identified by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;snapshot&lt;/strong&gt; is one reported value for an indicator, subject, and measurement
period.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;measurement period&lt;/strong&gt; is the half-open interval &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[periodStart, periodEnd)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;original snapshot&lt;/strong&gt; is the first snapshot occupying an exact subject,
indicator, and period slot.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;correction chain&lt;/strong&gt; is a linear sequence of snapshots connected by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;terminal snapshot&lt;/strong&gt; is a snapshot whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; equals zero.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;methodology&lt;/strong&gt; is the documented process used to measure or calculate a
reported value.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;attestation&lt;/strong&gt; is an append-only endorsement or dispute attached to a
specific snapshot.&lt;/p&gt;

&lt;h3 id=&quot;sentinel-value&quot;&gt;Sentinel Value&lt;/h3&gt;

&lt;p&gt;Implementations MUST use:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex == NO_CORRECTION&lt;/code&gt; identifies an original snapshot.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex == 0&lt;/code&gt; identifies a snapshot with no successor correction.&lt;/p&gt;

&lt;p&gt;Index zero is safe as the corrected-by sentinel because every correction index
is greater than the snapshot it corrects and therefore cannot be zero.&lt;/p&gt;

&lt;h3 id=&quot;core-snapshot-interface&quot;&gt;Core Snapshot Interface&lt;/h3&gt;

&lt;p&gt;A compliant log MUST implement:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IImpactSnapshotLog&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IndicatorSnapshot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodStart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reportedBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reportedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctedByIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SnapshotRecorded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodStart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reportedBy&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodStart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IndicatorSnapshot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorSnapshotCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorSnapshotAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ordinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestIndicatorSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentSnapshotForPeriod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodStart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodEnd&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;value-decimal-and-unit-semantics&quot;&gt;Value, Decimal, and Unit Semantics&lt;/h3&gt;

&lt;p&gt;The represented quantity is:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;value * 10^(-decimals)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; is signed because an impact measurement can be negative. This ERC does
not impose a maximum decimal precision below the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint8&lt;/code&gt; type limit. Consumers
MUST handle the declared precision safely and MUST NOT assume the value is
nonnegative.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt; SHOULD be the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; hash of a documented canonical unit string.
Applications SHOULD use International System of Units (SI) or Unified Code for
Units of Measure (UCUM)-compatible representations when available and MUST
document exact case, spelling, pluralization, and conversion rules for custom
or zero-valued unit identifiers.&lt;/p&gt;

&lt;p&gt;This ERC does not require a nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorId&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt;.
Applications requiring stricter namespaces MUST enforce and document them.&lt;/p&gt;

&lt;h3 id=&quot;measurement-periods&quot;&gt;Measurement Periods&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodStart&lt;/code&gt; is inclusive and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodEnd&lt;/code&gt; is exclusive.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordSnapshot&lt;/code&gt; MUST revert unless:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;periodStart &amp;lt; periodEnd &amp;lt;= block.timestamp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Only completed measurement periods can be recorded.&lt;/p&gt;

&lt;p&gt;An exact period slot is identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, indicatorId, periodStart,
periodEnd)&lt;/code&gt;. A log MUST accept at most one original snapshot for an exact slot.
Once occupied, revisions to that slot MUST use correction provenance.&lt;/p&gt;

&lt;p&gt;Different periods MAY overlap. This ERC does not determine whether overlapping
measurements are additive, duplicative, or methodologically compatible.&lt;/p&gt;

&lt;h3 id=&quot;recording-semantics&quot;&gt;Recording Semantics&lt;/h3&gt;

&lt;p&gt;Snapshot indices MUST be zero-based and scoped per &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;. The returned
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapshotIndex&lt;/code&gt; MUST equal the subject’s snapshot count before the new snapshot
is appended.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordSnapshot&lt;/code&gt; MUST be restricted to authorized reporters. The authorization
mechanism is implementation defined and MUST be documented.&lt;/p&gt;

&lt;p&gt;For every accepted snapshot, the log MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;store the supplied snapshot fields;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reportedBy&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reportedAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to zero;&lt;/li&gt;
  &lt;li&gt;append the snapshot index to the indicator-specific index;&lt;/li&gt;
  &lt;li&gt;make the snapshot discoverable for its exact period; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SnapshotRecorded&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyHash&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyURI&lt;/code&gt; MUST NOT be
empty.&lt;/p&gt;

&lt;p&gt;The methodology hash MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; of the exact methodology document
bytes under a documented representation. Consumers MUST retrieve the document
and reproduce the commitment before relying on it.&lt;/p&gt;

&lt;h3 id=&quot;correction-semantics&quot;&gt;Correction Semantics&lt;/h3&gt;

&lt;p&gt;An original snapshot MUST use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex == NO_CORRECTION&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A correction MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;identify an earlier snapshot under the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;use the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodStart&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodEnd&lt;/code&gt; as its target;&lt;/li&gt;
  &lt;li&gt;target a snapshot whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; is zero; and&lt;/li&gt;
  &lt;li&gt;be authorized under the implementation’s documented correction policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a correction is accepted, the log MUST set the target snapshot’s
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to the new snapshot index. No other target field may change.&lt;/p&gt;

&lt;p&gt;Each snapshot can be corrected at most once, preventing forks. A correction
snapshot can itself be corrected, producing a linear chain.&lt;/p&gt;

&lt;p&gt;The correction policy MUST NOT permit an ordinary reporter to correct another
reporter’s snapshot merely because both addresses can report. It MAY authorize
the original reporter, a designated corrector, or an administrator.&lt;/p&gt;

&lt;p&gt;A correction MAY change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimals&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt;, methodology, and reporter,
subject to the active methodology rules of an implementation supporting the
methodology extension.&lt;/p&gt;

&lt;h3 id=&quot;snapshot-queries&quot;&gt;Snapshot Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getSnapshot&lt;/code&gt; MUST return the complete stored snapshot and MUST revert when
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapshotIndex &amp;gt;= snapshotCount(subjectId)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapshotCount&lt;/code&gt; MUST return the number of snapshots recorded for a subject.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorSnapshotCount&lt;/code&gt; MUST return the number of snapshots recorded for an
exact subject and indicator, including corrections.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorSnapshotAt&lt;/code&gt; MUST return the per-subject snapshot index at the
specified zero-based indicator ordinal and MUST revert when the ordinal is
outside the indicator-specific index.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestIndicatorSnapshot&lt;/code&gt; MUST return the most recently recorded snapshot
index for the indicator and MUST revert when none exists. It describes
recording order, not the greatest &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodEnd&lt;/code&gt;, and does not necessarily identify
the current value for a particular period.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentSnapshotForPeriod&lt;/code&gt; MUST return the terminal snapshot index for the
exact subject, indicator, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodStart&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodEnd&lt;/code&gt;. It MUST revert when no
snapshot occupies that period slot.&lt;/p&gt;

&lt;p&gt;Consumers querying a specific reporting period SHOULD use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentSnapshotForPeriod&lt;/code&gt; rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestIndicatorSnapshot&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;indicator-identifiers&quot;&gt;Indicator Identifiers&lt;/h3&gt;

&lt;p&gt;The following indicator identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CARBON_OFFSET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:CARBON_OFFSET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CARBON_EMITTED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:CARBON_EMITTED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENERGY_GENERATED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:ENERGY_GENERATED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENERGY_SAVED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:ENERGY_SAVED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WATER_TREATED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:WATER_TREATED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JOBS_CREATED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:JOBS_CREATED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BENEFICIARIES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:BENEFICIARIES&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BIODIVERSITY_AREA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:BIODIVERSITY_AREA&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WASTE_DIVERTED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:WASTE_DIVERTED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Custom indicators SHOULD use:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;keccak256(&quot;ERC-8329:INDICATOR:&amp;lt;NAMESPACE&amp;gt;:&amp;lt;NAME&amp;gt;:&amp;lt;VERSION&amp;gt;&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Applications MUST document indicator definitions, boundaries, calculation
rules, and any mapping to external taxonomies. A generic identifier such as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(&quot;CUSTOM&quot;)&lt;/code&gt; SHOULD NOT be used because it does not provide semantic
separation.&lt;/p&gt;

&lt;h3 id=&quot;unit-identifiers&quot;&gt;Unit Identifiers&lt;/h3&gt;

&lt;p&gt;The following unit identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_TCO2E&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tCO2e&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_KWH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;kWh&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_M3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_FTE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;FTE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_PERSONS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;persons&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_HECTARES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hectares&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_TONNES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tonnes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UNIT_FTE&lt;/code&gt; uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FTE&lt;/code&gt; to denote full-time equivalent; the preimage string
remains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;FTE&quot;&lt;/code&gt; for stability.&lt;/p&gt;

&lt;p&gt;The defined indicator identifiers do not mandate one unit. Reporters and
consumers MUST inspect the stored unit and methodology rather than inferring a
unit from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorId&lt;/code&gt; alone.&lt;/p&gt;

&lt;h3 id=&quot;attestation-extension&quot;&gt;Attestation Extension&lt;/h3&gt;

&lt;p&gt;Attestation is OPTIONAL. An implementation supporting it MUST implement:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IImpactAttestation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Attestation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SnapshotAttested&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceURI&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAttestation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Attestation&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestSnapshot&lt;/code&gt; MUST reject an unknown snapshot and a zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceHash&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceURI&lt;/code&gt; MAY be empty.&lt;/p&gt;

&lt;p&gt;The implementation MUST set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestor&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;, set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestedAt&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;, append the attestation, emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SnapshotAttested&lt;/code&gt;, and
return its zero-based per-snapshot index.&lt;/p&gt;

&lt;p&gt;The reporter address stored on the snapshot MUST NOT attest that snapshot.
This is address-level separation only; it does not establish organizational,
affiliate, financial, or legal independence.&lt;/p&gt;

&lt;p&gt;Attestations MUST be immutable and non-deletable. The same attestor MAY submit
multiple attestations for the same snapshot, including a later assessment that
differs from an earlier one. Consumers MUST evaluate the complete history.&lt;/p&gt;

&lt;p&gt;Attestations MAY be added to corrected or nonterminal snapshots. Consumers MUST
decide whether an attestation to an earlier snapshot applies to any correction.
This ERC does not carry attestations forward automatically.&lt;/p&gt;

&lt;p&gt;Attestor authorization and credentialing are implementation defined and MUST
be documented.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestationCount&lt;/code&gt; MUST return the number of attestations for the exact snapshot.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAttestation&lt;/code&gt; MUST return the requested record and MUST revert when the
attestation index is outside that snapshot’s history.&lt;/p&gt;

&lt;h3 id=&quot;methodology-versioning-extension&quot;&gt;Methodology Versioning Extension&lt;/h3&gt;

&lt;p&gt;Methodology versioning is OPTIONAL. An implementation supporting it MUST
implement:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMethodologyVersioning&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MethodologySuperseded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveFromOrdinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;supersedeMethodology&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveFromOrdinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;activeMethodology&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pendingMethodology&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveFromOrdinal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;methodology-initialization-and-enforcement&quot;&gt;Methodology Initialization and Enforcement&lt;/h3&gt;

&lt;p&gt;The first snapshot for a subject and indicator MUST initialize its active
methodology to the snapshot’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyHash&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyURI&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After initialization, each new snapshot for that subject and indicator MUST use
the methodology hash active at its indicator-specific ordinal.&lt;/p&gt;

&lt;p&gt;The snapshot’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyURI&lt;/code&gt; MUST remain nonempty, but this ERC does not
require it to equal the URI returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeMethodology&lt;/code&gt;. Multiple locators
can reference the same committed methodology bytes. Consumers MUST verify the
retrieved bytes against the active hash.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeMethodology&lt;/code&gt; MUST return the methodology required for the next snapshot.
Before initialization, it MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; and an empty URI.&lt;/p&gt;

&lt;h3 id=&quot;methodology-supersession&quot;&gt;Methodology Supersession&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersedeMethodology&lt;/code&gt; MUST be restricted under a documented authorization
policy and MUST revert unless:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a methodology has already been initialized;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldMethodologyHash&lt;/code&gt; equals the active methodology;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newMethodologyHash&lt;/code&gt; is nonzero;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newMethodologyURI&lt;/code&gt; is nonempty;&lt;/li&gt;
  &lt;li&gt;no future supersession is already pending; and&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveFromOrdinal&lt;/code&gt; is greater than or equal to the current
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorSnapshotCount&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveFromOrdinal&lt;/code&gt; equals the current indicator count, the new
methodology becomes active immediately for the next snapshot.&lt;/p&gt;

&lt;p&gt;If it is greater than the current count, the supersession is pending. Existing
snapshots and snapshots before the effective ordinal continue to use the old
methodology. The new methodology becomes active when the current indicator
count reaches &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveFromOrdinal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Every successful supersession MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MethodologySuperseded&lt;/code&gt;. Existing
snapshot fields MUST NOT change.&lt;/p&gt;

&lt;p&gt;Implementations MAY impose a documented maximum future lookahead.&lt;/p&gt;

&lt;h3 id=&quot;pending-methodology-discovery&quot;&gt;Pending Methodology Discovery&lt;/h3&gt;

&lt;p&gt;While a future supersession has not reached its effective ordinal,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pendingMethodology&lt;/code&gt; MUST return the scheduled hash, URI, ordinal, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending == true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When no supersession is scheduled, or once its effective ordinal has been
reached, it MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;, an empty URI, zero, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once the ordinal has been reached, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeMethodology&lt;/code&gt; MUST expose the new
methodology even if no state-changing call has yet persisted an internal
transition.&lt;/p&gt;

&lt;p&gt;Historical values recalculated under a new methodology MUST be submitted as
corrections. They MUST NOT mutate existing snapshots.&lt;/p&gt;

&lt;h3 id=&quot;interface-detection&quot;&gt;Interface Detection&lt;/h3&gt;

&lt;p&gt;Compliant core logs MUST implement &lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IImpactSnapshotLog).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Implementations supporting optional extensions MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for the
corresponding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IImpactAttestation&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IMethodologyVersioning&lt;/code&gt; interface IDs.&lt;/p&gt;

&lt;p&gt;ERC-165 indicates interface support only. It does not establish measurement
accuracy, methodology validity, reporter or attestor credentials, evidence
quality, or independence.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;why-append-only-snapshots&quot;&gt;Why Append-Only Snapshots?&lt;/h3&gt;

&lt;p&gt;Impact data changes through new periods, corrected measurements, and revised
methodologies. Append-only storage preserves each assertion and makes revisions
visible instead of replacing history.&lt;/p&gt;

&lt;h3 id=&quot;why-one-original-per-exact-period&quot;&gt;Why One Original Per Exact Period?&lt;/h3&gt;

&lt;p&gt;Allowing multiple unrelated originals for the same indicator and exact period
would create competing current values. Requiring later revisions to use
correction provenance provides one resolvable chain.&lt;/p&gt;

&lt;h3 id=&quot;why-permit-overlapping-periods&quot;&gt;Why Permit Overlapping Periods?&lt;/h3&gt;

&lt;p&gt;Monthly, quarterly, annual, project-phase, and rolling measurements can
legitimately overlap. The interface cannot determine whether an overlap is
valid. Consumers aggregating values must apply methodology-specific rules to
avoid double counting.&lt;/p&gt;

&lt;h3 id=&quot;why-use-int256&quot;&gt;Why Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int256&lt;/code&gt;?&lt;/h3&gt;

&lt;p&gt;Measurements can be negative. Net emissions, energy savings relative to a
baseline, or other indicators can move in either direction.&lt;/p&gt;

&lt;h3 id=&quot;why-both-latest-and-period-specific-queries&quot;&gt;Why Both Latest and Period-Specific Queries?&lt;/h3&gt;

&lt;p&gt;The most recently recorded snapshot can concern an old period, such as a late
correction. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestIndicatorSnapshot&lt;/code&gt; supports monitoring recording activity,
while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentSnapshotForPeriod&lt;/code&gt; resolves the current value for an exact
period.&lt;/p&gt;

&lt;h3 id=&quot;why-require-methodology-metadata&quot;&gt;Why Require Methodology Metadata?&lt;/h3&gt;

&lt;p&gt;A value and unit are insufficient without the process that produced them.
Requiring both a commitment and a retrieval reference makes the declared
methodology independently verifiable when the document remains available.&lt;/p&gt;

&lt;h3 id=&quot;why-methodology-versioning-as-an-extension&quot;&gt;Why Methodology Versioning as an Extension?&lt;/h3&gt;

&lt;p&gt;Some deployments need only immutable per-snapshot methodology references.
Others require a governed active methodology for future reports. Separating the
extension allows the core log to remain usable without prescribing methodology
governance.&lt;/p&gt;

&lt;h3 id=&quot;why-attestation-as-an-extension&quot;&gt;Why Attestation as an Extension?&lt;/h3&gt;

&lt;p&gt;Not every deployment requires endorsement or dispute records. The optional
interface permits independent assessment histories without making credential
policy part of the core snapshot log.&lt;/p&gt;

&lt;h3 id=&quot;why-not-replace-earlier-attestations&quot;&gt;Why Not Replace Earlier Attestations?&lt;/h3&gt;

&lt;p&gt;An attestor’s changed view is itself relevant history. Appending the later
assessment preserves both statements and lets consumers apply their own
recency and credential policies.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This ERC introduces new interfaces and does not modify existing token,
registry, credential, attestation, or accounting standards.&lt;/p&gt;

&lt;p&gt;An existing application can deploy a companion snapshot log and use its own
application-defined subject namespace. No token contract changes are required
unless the token itself records snapshots.&lt;/p&gt;

&lt;p&gt;Implementations can adopt only the core interface or additionally expose either
optional extension. Consumers use ERC-165 to detect supported interfaces.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;zero-based per-subject indexing and subject isolation;&lt;/li&gt;
  &lt;li&gt;per-indicator counts, ordinals, and latest-recorded lookup;&lt;/li&gt;
  &lt;li&gt;completed, zero-length, and future period validation;&lt;/li&gt;
  &lt;li&gt;positive, zero, and negative values with varying decimals;&lt;/li&gt;
  &lt;li&gt;methodology hash and URI requirements;&lt;/li&gt;
  &lt;li&gt;one original per exact period;&lt;/li&gt;
  &lt;li&gt;overlapping but nonidentical periods;&lt;/li&gt;
  &lt;li&gt;correction bounds, authorization, period matching, and fork prevention;&lt;/li&gt;
  &lt;li&gt;multi-step correction chains and exact-period terminal lookup;&lt;/li&gt;
  &lt;li&gt;methodology initialization and active-methodology enforcement;&lt;/li&gt;
  &lt;li&gt;immediate and future methodology supersession;&lt;/li&gt;
  &lt;li&gt;pending methodology hash, URI, ordinal, and activation discovery;&lt;/li&gt;
  &lt;li&gt;pending-supersession exclusivity and implementation lookahead limits;&lt;/li&gt;
  &lt;li&gt;attestation evidence requirements and empty evidence URIs;&lt;/li&gt;
  &lt;li&gt;same-address self-attestation rejection;&lt;/li&gt;
  &lt;li&gt;repeated endorsement and dispute histories;&lt;/li&gt;
  &lt;li&gt;attestations to current and corrected snapshots;&lt;/li&gt;
  &lt;li&gt;unknown snapshot and attestation queries; and&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection for every supported interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;A Solidity reference implementation, constants library, example integrations,
unit tests, Medusa property tests, deployment scripts, and independent audit are
linked from the official discussion thread.&lt;/p&gt;

&lt;p&gt;The reference implementation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;uses reporter, attestor, and administrator roles;&lt;/li&gt;
  &lt;li&gt;allows a reporter to correct its own snapshot and an administrator-reporter
to correct another reporter’s snapshot;&lt;/li&gt;
  &lt;li&gt;rejects completed-period duplicates unless correction provenance is used;&lt;/li&gt;
  &lt;li&gt;implements all three interfaces;&lt;/li&gt;
  &lt;li&gt;blocks same-address self-attestation; and&lt;/li&gt;
  &lt;li&gt;limits scheduled methodology supersession to 1,000 future indicator
ordinals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Role assignments and the 1,000-ordinal lookahead are reference deployment
choices rather than core interface requirements.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;reporter-trust&quot;&gt;Reporter Trust&lt;/h3&gt;

&lt;p&gt;The log proves that an authorized address reported a value. It does not verify
the measurement, source data, calculation, unit, period boundaries, or
methodology application. False data remains false when recorded immutably.&lt;/p&gt;

&lt;h3 id=&quot;methodology-integrity-and-availability&quot;&gt;Methodology Integrity and Availability&lt;/h3&gt;

&lt;p&gt;A methodology commitment is useful only when consumers can obtain the exact
document representation and reproduce its hash. A URI can disappear, change
content, require authorization, or expose sensitive information. Deployments
should use durable storage and document the hashing representation.&lt;/p&gt;

&lt;h3 id=&quot;methodology-governance&quot;&gt;Methodology Governance&lt;/h3&gt;

&lt;p&gt;An authorized party can supersede a methodology with one that produces more
favorable results. Events and pending-methodology queries make the transition
visible but do not establish its legitimacy. Consumers must evaluate
methodology governance independently.&lt;/p&gt;

&lt;h3 id=&quot;correction-authorization-and-chain-length&quot;&gt;Correction Authorization and Chain Length&lt;/h3&gt;

&lt;p&gt;A weak correction policy can let one reporter supersede another’s measurement.
Implementations must document correction authority.&lt;/p&gt;

&lt;p&gt;Period lookup traverses correction pointers. Although chains are linear and
acyclic, excessive corrections can make on-chain resolution expensive.&lt;/p&gt;

&lt;h3 id=&quot;attestor-credentials-and-independence&quot;&gt;Attestor Credentials and Independence&lt;/h3&gt;

&lt;p&gt;Blocking the exact reporter address prevents only direct self-attestation. The
same organization can control multiple addresses, and an attestor role does not
prove professional qualification, financial independence, or legal authority.
Consumers must evaluate credential and conflict policies.&lt;/p&gt;

&lt;h3 id=&quot;conflicting-attestations&quot;&gt;Conflicting Attestations&lt;/h3&gt;

&lt;p&gt;The interface permits multiple endorsements and disputes without computing a
consensus result. Counting addresses is not a reliable trust model because
addresses are cheap and credentials can differ. Consumers need an external
attestor-selection and weighting policy.&lt;/p&gt;

&lt;h3 id=&quot;double-counting-and-overlapping-claims&quot;&gt;Double Counting and Overlapping Claims&lt;/h3&gt;

&lt;p&gt;Exact-period uniqueness applies only within one subject and indicator slot.
Overlapping periods, related indicators, multiple subjects, and independent
registries can represent the same underlying impact. Consumers must reconcile
boundaries and methodologies before aggregation.&lt;/p&gt;

&lt;h3 id=&quot;privacy&quot;&gt;Privacy&lt;/h3&gt;

&lt;p&gt;Subjects, values, periods, methodology URIs, and attestation evidence can reveal
commercial, personal, geographic, or site-sensitive information. Public-chain
deployments should use opaque subject identifiers, redacted documents, and
access-controlled evidence distribution where appropriate. Hashing low-entropy
sensitive data without a secret salt does not provide meaningful privacy.&lt;/p&gt;

&lt;h3 id=&quot;unit-and-decimal-handling&quot;&gt;Unit and Decimal Handling&lt;/h3&gt;

&lt;p&gt;Consumers that ignore units, decimals, sign, or conversion rules can produce
materially incorrect aggregates. Implementations should use checked arithmetic,
explicit normalization, and methodology-aware conversion.&lt;/p&gt;

&lt;h3 id=&quot;timestamp-dependence&quot;&gt;Timestamp Dependence&lt;/h3&gt;

&lt;p&gt;Completed-period validation uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;, which block producers can
influence within protocol bounds. Applications requiring exact wall-clock
cutoffs must account for that uncertainty.&lt;/p&gt;

&lt;h3 id=&quot;storage-growth&quot;&gt;Storage Growth&lt;/h3&gt;

&lt;p&gt;Snapshots and attestations are append-only. Authorization, reporting-frequency
policy, and operational monitoring are necessary to control storage costs and
spam.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8329</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8329</guid>
      </item>
      
    
      
      
      <item>
        <title>Subject-Linked NAV Snapshot Oracle</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8330 - Subject-Linked NAV Snapshot Oracle&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8330-subject-linked-nav-snapshot-oracle/28939&quot;&gt;https://ethereum-magicians.org/t/erc-8330-subject-linked-nav-snapshot-oracle/28939&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines an interface for publishing
and querying subject-linked net asset value (NAV) snapshots. Each stream is
keyed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, currency)&lt;/code&gt; and
has one configured NAV basis. Snapshots include signed NAV, decimal precision,
valuation and publication timestamps, provider attribution, methodology
references, and correction provenance.&lt;/p&gt;

&lt;p&gt;The core interface supports raw and staleness-aware latest-value queries,
provider-specific history, correction-chain resolution, and administrative
invalidation that preserves records while excluding invalid snapshots from
current-value queries. An optional aggregation interface defines deterministic
lower-median aggregation across provider submissions sharing a valuation
timestamp.&lt;/p&gt;

&lt;p&gt;This ERC standardizes publication and query semantics. It does not calculate
NAV, credential providers, verify methodologies, establish asset backing, or
guarantee that NAV is an executable market or redemption price.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Periodic valuations for funds, private credit, real estate, infrastructure,
commodities, and other illiquid or administratively priced assets differ from
continuous exchange prices. Consumers need to know what the value represents,
when the underlying valuation was measured, when it was published, who supplied
it, and whether it is too old for the intended use.&lt;/p&gt;

&lt;p&gt;Existing price and quote interfaces do not necessarily preserve valuation
history, provider identity, methodology references, restatement provenance, or
separate publication-age and valuation-age checks. Bespoke NAV contracts also
use incompatible stream keys and latest-value semantics.&lt;/p&gt;

&lt;p&gt;This ERC provides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;independent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, currency)&lt;/code&gt; NAV streams;&lt;/li&gt;
  &lt;li&gt;stream-level basis configuration preventing provider disagreement over
per-unit, per-share, or total interpretation;&lt;/li&gt;
  &lt;li&gt;provider-attributed historical snapshots;&lt;/li&gt;
  &lt;li&gt;one original provider submission per valuation timestamp;&lt;/li&gt;
  &lt;li&gt;fork-free corrections and current-chain helpers;&lt;/li&gt;
  &lt;li&gt;administrative invalidation for compromised or disputed terminal snapshots;&lt;/li&gt;
  &lt;li&gt;separate publication and valuation staleness signals; and&lt;/li&gt;
  &lt;li&gt;optional deterministic aggregation with quorum and deviation reporting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interface can serve vaults, settlement systems, reporting applications, and
other consumers while leaving valuation policy and provider governance to each
deployment.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;definitions&quot;&gt;Definitions&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;stream&lt;/strong&gt; is the namespace identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, currency)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;NAV basis&lt;/strong&gt; states whether NAV represents one underlying unit, one share or
token, or the total value of the subject.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;provider&lt;/strong&gt; is the address recorded as publishing a snapshot.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;valuation timestamp&lt;/strong&gt; is the asserted as-of time of the valuation.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;publication timestamp&lt;/strong&gt; is the block timestamp at which the snapshot was
recorded.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;terminal snapshot&lt;/strong&gt; is a snapshot whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; equals
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;current snapshot&lt;/strong&gt; is a terminal snapshot that has not been invalidated.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;publication heartbeat&lt;/strong&gt; is the maximum accepted time since publication.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;maximum valuation age&lt;/strong&gt; is the maximum accepted time since the valuation
timestamp.&lt;/p&gt;

&lt;h3 id=&quot;sentinel-values&quot;&gt;Sentinel Values&lt;/h3&gt;

&lt;p&gt;Implementations MUST use:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTED_BY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTION&lt;/code&gt; identifies an original snapshot. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt; identifies a
snapshot with no successor correction.&lt;/p&gt;

&lt;p&gt;Index zero is safe as the corrected-by sentinel because a correction index is
always greater than its target and therefore cannot be zero.&lt;/p&gt;

&lt;h3 id=&quot;core-interface&quot;&gt;Core Interface&lt;/h3&gt;

&lt;p&gt;A compliant oracle MUST implement:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INAVSnapshotOracle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVSnapshot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctedByIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVPublished&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StalenessConfigUpdated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heartbeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxValuationAge&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVBasisConfigured&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVSnapshotInvalidated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalidatedBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishNAV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setNAVBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalidateSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSnapshotInvalidated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setStalenessConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heartbeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxValuationAge&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;streamNAVBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestNAV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestNAVStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isPublishStale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isValuationStale&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NAVSnapshot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentSnapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSnapshotCurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestNAVByProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NAVSnapshot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerSnapshotCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerSnapshotAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ordinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heartbeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxValuationAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;stream-scope&quot;&gt;Stream Scope&lt;/h3&gt;

&lt;p&gt;Snapshot indices MUST be zero-based and scoped independently to each
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, currency)&lt;/code&gt; stream.&lt;/p&gt;

&lt;p&gt;This ERC does not require nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currency&lt;/code&gt; values.
Applications requiring stricter namespaces MUST enforce and document them.&lt;/p&gt;

&lt;h3 id=&quot;nav-basis&quot;&gt;NAV Basis&lt;/h3&gt;

&lt;p&gt;The following basis identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PER_UNIT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:NAV_BASIS:PER_UNIT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PER_SHARE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:NAV_BASIS:PER_SHARE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TOTAL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:NAV_BASIS:TOTAL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_UNIT&lt;/code&gt; represents one unit of the underlying asset. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_SHARE&lt;/code&gt; represents
one share or token in a fund or pool. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TOTAL&lt;/code&gt; represents the total NAV of the
subject.&lt;/p&gt;

&lt;p&gt;An authorized configurer MUST call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setNAVBasis&lt;/code&gt; before the first publication
to a stream. The function MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;accept only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_UNIT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_SHARE&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TOTAL&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;reject a stream that already contains snapshots;&lt;/li&gt;
  &lt;li&gt;reject a stream whose basis was already configured;&lt;/li&gt;
  &lt;li&gt;store the basis permanently; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVBasisConfigured&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;streamNAVBasis&lt;/code&gt; MUST return the configured basis or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; for an
unconfigured stream.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishNAV&lt;/code&gt; MUST reject an unconfigured stream and any supplied basis that
does not equal its configured basis.&lt;/p&gt;

&lt;p&gt;Provider-selected basis changes are prohibited. Stream-level configuration
prevents incompatible submissions from disabling aggregation at a shared
valuation timestamp.&lt;/p&gt;

&lt;h3 id=&quot;nav-and-decimal-semantics&quot;&gt;NAV and Decimal Semantics&lt;/h3&gt;

&lt;p&gt;The represented NAV is:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nav * 10^(-decimals)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nav&lt;/code&gt; is signed because liabilities can exceed assets. Consumers MUST handle
negative and zero values explicitly.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishNAV&lt;/code&gt; MUST reject:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimals &amp;gt; 18&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nav == type(int256).min&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;a magnitude greater than:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This bound ensures that a conforming aggregation implementation can safely
normalize every accepted value to 18 decimal places.&lt;/p&gt;

&lt;h3 id=&quot;currency-identifiers&quot;&gt;Currency Identifiers&lt;/h3&gt;

&lt;p&gt;The following fiat currency identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;USD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:USD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EUR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:EUR&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GBP&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:GBP&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:KES&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ZMW&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:ZMW&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Additional ISO 4217 currencies SHOULD use:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;keccak256(&quot;ERC-8330:CURRENCY:&amp;lt;CODE&amp;gt;&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Token-denominated streams SHOULD derive currency as:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:TOKEN&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;chainId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tokenAddress&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Including both chain ID and token address prevents equal addresses on different
chains from sharing a currency identifier.&lt;/p&gt;

&lt;p&gt;Other denominations SHOULD use an application-documented, domain-separated
identifier and MUST NOT reuse an ISO code unless the denomination is that fiat
currency.&lt;/p&gt;

&lt;h3 id=&quot;publication-semantics&quot;&gt;Publication Semantics&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishNAV&lt;/code&gt; MUST be restricted to authorized providers. Provider authorization
is implementation defined and MUST be documented.&lt;/p&gt;

&lt;p&gt;For every accepted snapshot, the oracle MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;provider&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishedAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;append the snapshot to the stream and provider history;&lt;/li&gt;
  &lt;li&gt;update current-value and provider/timestamp indexes;&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVPublished&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;return the new stream-scoped index.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valuationTimestamp&lt;/code&gt; MUST NOT be greater than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyHash&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyURI&lt;/code&gt; MAY be empty only when the deployment documents how consumers
retrieve the exact methodology representation out of band. The hash derivation
MUST be documented. It MAY commit to raw document bytes or a deterministic
document-bundle commitment.&lt;/p&gt;

&lt;p&gt;The oracle MUST reject the call if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; cannot be represented as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;provider-and-valuation-uniqueness&quot;&gt;Provider and Valuation Uniqueness&lt;/h3&gt;

&lt;p&gt;A provider MAY publish at most one current original snapshot for an exact
stream and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valuationTimestamp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If that provider/timestamp slot is occupied, a revision MUST use correction
provenance. Other providers MAY publish independent originals for the same
stream and valuation timestamp.&lt;/p&gt;

&lt;h3 id=&quot;correction-semantics&quot;&gt;Correction Semantics&lt;/h3&gt;

&lt;p&gt;An original snapshot MUST use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex == NO_CORRECTION&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A correction MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;identify an earlier snapshot in the same stream;&lt;/li&gt;
  &lt;li&gt;target a terminal, non-invalidated snapshot;&lt;/li&gt;
  &lt;li&gt;be published by the same provider as the target;&lt;/li&gt;
  &lt;li&gt;use the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valuationTimestamp&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;navBasis&lt;/code&gt; as the target; and&lt;/li&gt;
  &lt;li&gt;target the provider’s current snapshot for that valuation timestamp.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When accepted, the target’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; MUST be set to the new snapshot
index. No other target field may change.&lt;/p&gt;

&lt;p&gt;Before invalidation, each snapshot can have at most one successor correction.
A correction can itself be corrected, creating a linear current chain. A
correction MAY change NAV, decimals, methodology, and methodology URI.&lt;/p&gt;

&lt;h3 id=&quot;invalidation&quot;&gt;Invalidation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;invalidateSnapshot&lt;/code&gt; MUST be restricted under a documented administrative or
governance policy. It MUST reject a zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reasonHash&lt;/code&gt;, unknown snapshot,
nonterminal snapshot, or already invalidated snapshot.&lt;/p&gt;

&lt;p&gt;On success, the oracle MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;preserve the invalidated snapshot record;&lt;/li&gt;
  &lt;li&gt;permanently mark it invalidated;&lt;/li&gt;
  &lt;li&gt;exclude it from latest-value, provider-latest, current-chain, quorum,
aggregation, and deviation calculations defined by the optional Aggregation
Extension below;&lt;/li&gt;
  &lt;li&gt;recompute affected latest and quorum pointers; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVSnapshotInvalidated&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If an original snapshot is invalidated, its provider/timestamp slot MUST become
available for a replacement original.&lt;/p&gt;

&lt;p&gt;If a correction is invalidated, its direct predecessor MUST become terminal
again and the provider/timestamp slot MUST point to that predecessor. The
provider can then publish a replacement correction.&lt;/p&gt;

&lt;p&gt;In a longer correction chain, invalidating the terminal restores only its
direct predecessor. Administrators MAY unwind additional snapshots by
invalidating each newly restored terminal in turn.&lt;/p&gt;

&lt;p&gt;Invalidation does not erase &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; history. Replacement corrections
can create multiple historical records that reference the same predecessor,
but only one non-invalidated branch can be current. Consumers reconstructing
history MUST account for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVSnapshotInvalidated&lt;/code&gt; events.&lt;/p&gt;

&lt;p&gt;An invalidated snapshot MUST NOT be corrected or restored.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isSnapshotInvalidated&lt;/code&gt; MUST revert for an unknown index and otherwise return
the permanent invalidation state.&lt;/p&gt;

&lt;h3 id=&quot;current-chain-queries&quot;&gt;Current-Chain Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentSnapshotIndex&lt;/code&gt; MUST revert for an unknown index. It MUST follow
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to a terminal snapshot and return that index only if the
terminal is not invalidated. It MUST revert when no current terminal remains.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isSnapshotCurrent&lt;/code&gt; MUST revert for an unknown index and otherwise return
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; only when the snapshot is terminal and not invalidated.&lt;/p&gt;

&lt;h3 id=&quot;latest-nav-queries&quot;&gt;Latest NAV Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAV&lt;/code&gt; MUST return the current snapshot with the greatest
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valuationTimestamp&lt;/code&gt;, regardless of staleness. When multiple current snapshots
share that valuation timestamp, it MUST return the most recently published one;
if publication timestamps are equal, the greater snapshot index wins.&lt;/p&gt;

&lt;p&gt;A late correction to an older valuation timestamp MUST NOT replace a current
snapshot with a later valuation timestamp as the stream’s latest NAV.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAV&lt;/code&gt; MUST revert when no current snapshot exists.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAVByProvider&lt;/code&gt; MUST apply the same valuation and publication ordering to
that provider’s current snapshots and MUST revert when the provider has no
current snapshot.&lt;/p&gt;

&lt;h3 id=&quot;historical-queries&quot;&gt;Historical Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getSnapshot&lt;/code&gt; MUST return the preserved record for any valid index, including a
corrected or invalidated snapshot, and MUST revert for an unknown index.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapshotCount&lt;/code&gt; MUST include every published snapshot, including corrections
and invalidated records.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSnapshotCount&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSnapshotAt&lt;/code&gt; MUST expose the provider’s
complete publication history, including corrected and invalidated snapshots.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSnapshotAt&lt;/code&gt; MUST revert for an out-of-range ordinal.&lt;/p&gt;

&lt;h3 id=&quot;staleness-configuration&quot;&gt;Staleness Configuration&lt;/h3&gt;

&lt;p&gt;An authorized configurer MUST be able to set a nonzero publication &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heartbeat&lt;/code&gt;
and nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maxValuationAge&lt;/code&gt; independently for each stream. Successful changes
MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StalenessConfigUpdated&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heartbeat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maxValuationAge&lt;/code&gt; MUST return zero while the corresponding
value is unconfigured.&lt;/p&gt;

&lt;p&gt;Configuration authorization is implementation defined and MUST be documented.&lt;/p&gt;

&lt;h3 id=&quot;staleness-semantics&quot;&gt;Staleness Semantics&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAVStatus&lt;/code&gt; MUST return the same snapshot selected by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAV&lt;/code&gt; plus two
independent flags:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;isPublishStale = block.timestamp &amp;gt; publishedAt + heartbeat
isValuationStale =
    block.timestamp &amp;gt; valuationTimestamp + maxValuationAge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A value is not stale exactly at its threshold boundary.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAVStatus&lt;/code&gt; MUST revert when either staleness threshold is unconfigured or
when no current snapshot exists. It MUST NOT mutate state or emit events.&lt;/p&gt;

&lt;p&gt;Consumers MUST evaluate both flags. Recent publication of an old valuation can
be publication-fresh but valuation-stale.&lt;/p&gt;

&lt;h3 id=&quot;aggregation-extension&quot;&gt;Aggregation Extension&lt;/h3&gt;

&lt;p&gt;Aggregation is OPTIONAL. An implementation supporting it MUST implement:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INAVAggregation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVDeviationDetected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minNav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxNav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviationBps&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AggregationConfigUpdated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quorum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviationThresholdBps&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setAggregationConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quorum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviationThresholdBps&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aggregatedNAV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isPublishStale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isValuationStale&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerSubmissionCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerSubmissionAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishedAt&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestAggregationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quorum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviationThreshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;aggregation-configuration&quot;&gt;Aggregation Configuration&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setAggregationConfig&lt;/code&gt; MUST be restricted to authorized configurers. It MUST
reject a zero quorum and a deviation threshold greater than 10,000 basis
points. Implementations MAY impose a documented maximum provider count and MUST
reject a quorum above that maximum.&lt;/p&gt;

&lt;p&gt;Successful configuration MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AggregationConfigUpdated&lt;/code&gt; and MUST account
for historical timestamps that already satisfy the new quorum.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quorum&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deviationThreshold&lt;/code&gt; MUST return zero while unconfigured.&lt;/p&gt;

&lt;h3 id=&quot;eligible-provider-submissions&quot;&gt;Eligible Provider Submissions&lt;/h3&gt;

&lt;p&gt;For one valuation timestamp, at most one submission per provider is eligible.
That submission is the provider’s current snapshot for the timestamp.
Corrected, invalidated, and detached historical snapshots MUST be excluded.&lt;/p&gt;

&lt;p&gt;A valuation timestamp is aggregation-eligible when its number of eligible
providers is at least the configured quorum.&lt;/p&gt;

&lt;p&gt;The latest aggregation timestamp MUST be the greatest eligible valuation
timestamp, not the timestamp of the most recent publication.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestAggregationTimestamp&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSubmissionCount&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSubmissionAt&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aggregatedNAV&lt;/code&gt; MUST revert when quorum is
unconfigured or no valuation timestamp meets quorum.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSubmissionCount&lt;/code&gt; MUST return the eligible provider count at the latest
aggregation timestamp.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSubmissionAt&lt;/code&gt; MUST return eligible submissions in provider first-seen
order for that timestamp and MUST revert when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt; is outside the eligible
set.&lt;/p&gt;

&lt;h3 id=&quot;median-aggregation&quot;&gt;Median Aggregation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aggregatedNAV&lt;/code&gt; MUST normalize all eligible values to the greatest submitted
decimal precision:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;normalizedNav = nav * 10^(maxDecimals - decimals)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It MUST sort normalized values in ascending order and return:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;values[(providerCount - 1) / 2]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This selects the lower median for an even provider count.&lt;/p&gt;

&lt;p&gt;The returned basis MUST equal the configured stream basis. The returned
valuation timestamp MUST equal the latest aggregation timestamp. The returned
provider count MUST equal the number of eligible submissions.&lt;/p&gt;

&lt;p&gt;For aggregate publication staleness, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishedAt&lt;/code&gt; MUST be treated as the
greatest publication timestamp among eligible submissions. Aggregate valuation
staleness uses the shared valuation timestamp.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aggregatedNAV&lt;/code&gt; MUST revert until both staleness thresholds are configured.&lt;/p&gt;

&lt;h3 id=&quot;deviation-detection&quot;&gt;Deviation Detection&lt;/h3&gt;

&lt;p&gt;After a successful publication at a valuation timestamp that meets quorum, the
non-view publication path MUST calculate:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;spread = maxNav - minNav
deviationBps = spread * 10_000 / abs(medianNav)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The calculation MUST account safely for signed values. If the spread is zero,
deviation is zero. If the median is zero while spread is nonzero, or if the
calculation would overflow, deviation MUST saturate at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(uint256).max&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deviationBps &amp;gt; deviationThresholdBps&lt;/code&gt;, the oracle MUST emit
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVDeviationDetected&lt;/code&gt; from the publication transaction. Equality does not
trigger the event.&lt;/p&gt;

&lt;p&gt;Deviation events are alerts. They do not invalidate submissions or prevent
aggregation.&lt;/p&gt;

&lt;h3 id=&quot;interface-detection&quot;&gt;Interface Detection&lt;/h3&gt;

&lt;p&gt;Compliant core oracles MUST implement &lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(INAVSnapshotOracle).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Implementations supporting aggregation MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(INAVAggregation).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ERC-165 indicates interface support only. It does not establish provider
credentials, NAV accuracy, methodology validity, liquidity, redemption rights,
or use of the oracle by a consuming contract.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;why-key-streams-by-subject-and-currency&quot;&gt;Why Key Streams by Subject and Currency?&lt;/h3&gt;

&lt;p&gt;A subject can be valued in multiple denominations. Treating each pair as an
independent stream removes ambiguity and permits separate history, staleness,
and aggregation configuration.&lt;/p&gt;

&lt;h3 id=&quot;why-configure-nav-basis-at-stream-level&quot;&gt;Why Configure NAV Basis at Stream Level?&lt;/h3&gt;

&lt;p&gt;Per-unit, per-share, and total NAV differ materially. If providers can choose
basis independently, one mismatched submission can make a quorum set
incomparable or unavailable. Immutable stream-level basis configuration rejects
the mismatch before it enters the stream.&lt;/p&gt;

&lt;h3 id=&quot;why-separate-valuation-and-publication-timestamps&quot;&gt;Why Separate Valuation and Publication Timestamps?&lt;/h3&gt;

&lt;p&gt;A value can be published recently while describing an old valuation. Consumers
need both times to assess operational feed health and economic recency.&lt;/p&gt;

&lt;h3 id=&quot;why-signed-nav&quot;&gt;Why Signed NAV?&lt;/h3&gt;

&lt;p&gt;Liabilities can exceed assets. A signed representation avoids silently
excluding insolvent or leveraged subjects, while consumers remain responsible
for handling nonpositive values safely.&lt;/p&gt;

&lt;h3 id=&quot;why-corrections&quot;&gt;Why Corrections?&lt;/h3&gt;

&lt;p&gt;Valuations can be restated after administrator error, late information, audit
adjustments, or model changes. Correction links preserve the earlier assertion
and identify its successor.&lt;/p&gt;

&lt;h3 id=&quot;why-administrative-invalidation&quot;&gt;Why Administrative Invalidation?&lt;/h3&gt;

&lt;p&gt;Correction requires the original provider. If that provider is compromised,
revoked, or unavailable, a poisoned terminal snapshot could otherwise remain
current and continue to satisfy quorum. Invalidation excludes it without
deleting history and allows a valid replacement.&lt;/p&gt;

&lt;h3 id=&quot;why-latest-by-valuation-time&quot;&gt;Why Latest by Valuation Time?&lt;/h3&gt;

&lt;p&gt;A late correction for an older valuation should not displace a more recent
valuation as the stream’s raw latest value. Period recency and publication
recency answer different questions.&lt;/p&gt;

&lt;h3 id=&quot;why-lower-median-aggregation&quot;&gt;Why Lower-Median Aggregation?&lt;/h3&gt;

&lt;p&gt;Median aggregation resists a minority of extreme submissions. Selecting the
lower median for even sets makes the result deterministic without introducing
rounding between two signed values.&lt;/p&gt;

&lt;h3 id=&quot;why-dual-staleness&quot;&gt;Why Dual Staleness?&lt;/h3&gt;

&lt;p&gt;Publication heartbeat detects a feed that stopped updating. Maximum valuation
age detects publication of economically old data. Either condition can matter
independently.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-4626&quot;&gt;ERC-4626&lt;/a&gt; defines tokenized vault accounting and conversion
functions. This ERC can provide an external valuation input but does not define
vault accounting, deposits, withdrawals, or redemption guarantees.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7540&quot;&gt;ERC-7540&lt;/a&gt; extends ERC-4626 for asynchronous requests, and
&lt;a href=&quot;/EIPS/eip-7575&quot;&gt;ERC-7575&lt;/a&gt; supports multi-asset vaults. Both may consume NAV but
do not define this provider-attributed snapshot lifecycle.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This ERC introduces new interfaces and does not modify existing token, vault,
oracle, or accounting standards.&lt;/p&gt;

&lt;p&gt;Existing systems can deploy a companion oracle and map their asset or fund
identifier to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;. Integration is optional.&lt;/p&gt;

&lt;p&gt;Vault integrations should not call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAVStatus&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aggregatedNAV&lt;/code&gt; from
critical conversion paths unless configuration is guaranteed. These functions
revert when staleness configuration is absent. Adapters can validate and cache
an accepted NAV for non-reverting preview or conversion surfaces.&lt;/p&gt;

&lt;h2 id=&quot;test-cases&quot;&gt;Test Cases&lt;/h2&gt;

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;stream isolation by subject and currency;&lt;/li&gt;
  &lt;li&gt;one-time known-basis configuration and publication-before-configuration
rejection;&lt;/li&gt;
  &lt;li&gt;rejection of provider basis mismatch;&lt;/li&gt;
  &lt;li&gt;signed NAV, decimal, magnitude, and future-valuation bounds;&lt;/li&gt;
  &lt;li&gt;methodology hash requirements and documented empty-URI behavior;&lt;/li&gt;
  &lt;li&gt;provider/timestamp original uniqueness;&lt;/li&gt;
  &lt;li&gt;correction provider, timestamp, basis, terminal, and latest-slot guards;&lt;/li&gt;
  &lt;li&gt;correction-of-correction chains and current-state helpers;&lt;/li&gt;
  &lt;li&gt;latest selection by valuation timestamp rather than publication order;&lt;/li&gt;
  &lt;li&gt;provider history including corrected and invalidated records;&lt;/li&gt;
  &lt;li&gt;publication and valuation staleness before, at, and after each boundary;&lt;/li&gt;
  &lt;li&gt;staleness-aware query rejection while unconfigured;&lt;/li&gt;
  &lt;li&gt;original and correction invalidation;&lt;/li&gt;
  &lt;li&gt;predecessor restoration and replacement publication after invalidation;&lt;/li&gt;
  &lt;li&gt;latest-provider, latest-stream, and quorum recomputation after invalidation;&lt;/li&gt;
  &lt;li&gt;aggregation configuration and historical quorum discovery;&lt;/li&gt;
  &lt;li&gt;provider caps and quorum limits;&lt;/li&gt;
  &lt;li&gt;decimal normalization and lower-median selection;&lt;/li&gt;
  &lt;li&gt;latest eligible valuation-timestamp selection;&lt;/li&gt;
  &lt;li&gt;provider submission pagination and ordering;&lt;/li&gt;
  &lt;li&gt;corrected and invalidated submission exclusion;&lt;/li&gt;
  &lt;li&gt;deviation threshold, zero-median, and overflow saturation behavior;&lt;/li&gt;
  &lt;li&gt;fiat and token currency derivation; and&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;p&gt;A Solidity reference implementation, constants library, unit tests, Medusa
property tests, deployment configuration, and independent audit are linked from
the official discussion thread.&lt;/p&gt;

&lt;p&gt;The reference implementation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;uses provider, configurer, and administrator roles;&lt;/li&gt;
  &lt;li&gt;supports all core and aggregation functions in one contract;&lt;/li&gt;
  &lt;li&gt;caps providers per valuation timestamp at 64;&lt;/li&gt;
  &lt;li&gt;uses deterministic lower-median aggregation;&lt;/li&gt;
  &lt;li&gt;emits deviation alerts from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishNAV&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;recomputes affected indexes after administrative invalidation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Role assignments and the provider cap are reference deployment choices. The
stream basis, correction, invalidation, staleness, and deterministic aggregation
semantics are requirements of this ERC.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;nav-is-not-an-executable-price&quot;&gt;NAV Is Not an Executable Price&lt;/h3&gt;

&lt;p&gt;NAV is an accounting or valuation assertion. A token can trade above or below
NAV, and redemption can be gated, delayed, limited, or unavailable. Consumers
must not treat NAV as a liquid market price without separately validating
liquidity and redemption assumptions.&lt;/p&gt;

&lt;h3 id=&quot;provider-and-configurer-trust&quot;&gt;Provider and Configurer Trust&lt;/h3&gt;

&lt;p&gt;A provider can publish fabricated or mistaken values and methodologies. A
configurer can choose unsafe staleness or quorum settings. Implementations must
document authorization, governance, upgrade, and key-management policies.&lt;/p&gt;

&lt;p&gt;Revoking a provider role does not invalidate its existing snapshots. An
authorized invalidator must separately invalidate any snapshot that should no
longer participate in current queries.&lt;/p&gt;

&lt;h3 id=&quot;methodology-verification&quot;&gt;Methodology Verification&lt;/h3&gt;

&lt;p&gt;A methodology hash is useful only when consumers can obtain the committed
document representation and reproduce the hash. An empty or unavailable URI
can make independent verification impossible unless an out-of-band retrieval
process is documented.&lt;/p&gt;

&lt;h3 id=&quot;staleness-enforcement&quot;&gt;Staleness Enforcement&lt;/h3&gt;

&lt;p&gt;Staleness flags protect only consumers that check them. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAV&lt;/code&gt; deliberately
returns raw data without a staleness decision. Pricing and settlement paths
should use validated status or a controlled adapter.&lt;/p&gt;

&lt;h3 id=&quot;negative-and-zero-nav&quot;&gt;Negative and Zero NAV&lt;/h3&gt;

&lt;p&gt;Consuming contracts that assume positive NAV can underflow, divide by zero, or
misprice assets. They must define explicit behavior for zero and negative
values.&lt;/p&gt;

&lt;h3 id=&quot;provider-collusion-and-correlated-error&quot;&gt;Provider Collusion and Correlated Error&lt;/h3&gt;

&lt;p&gt;Median and quorum reduce single-provider influence but do not prevent collusion,
shared data-source failures, or common methodology errors. Address count does
not prove provider independence.&lt;/p&gt;

&lt;h3 id=&quot;invalidation-authority-and-cost&quot;&gt;Invalidation Authority and Cost&lt;/h3&gt;

&lt;p&gt;Invalidation can remove legitimate data and change latest or aggregate values.
The authority should be strongly controlled and every reason commitment should
be independently reviewable.&lt;/p&gt;

&lt;p&gt;Recomputing latest and quorum pointers can require work proportional to stream
history. Production implementations with long histories should use bounded or
checkpointed indexing while preserving the specified results.&lt;/p&gt;

&lt;h3 id=&quot;correction-and-invalidation-interpretation&quot;&gt;Correction and Invalidation Interpretation&lt;/h3&gt;

&lt;p&gt;Invalidation can detach a historical correction and permit a replacement branch.
Consumers must combine correction pointers with invalidation state and events;
following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; alone does not identify the current branch.&lt;/p&gt;

&lt;h3 id=&quot;front-running-valuation-updates&quot;&gt;Front-Running Valuation Updates&lt;/h3&gt;

&lt;p&gt;Material NAV changes visible before inclusion can enable transactions against
an older accepted value. Deployments should consider private submission,
commit-reveal publication, settlement pauses, or delayed activation when the
economic risk justifies the complexity.&lt;/p&gt;

&lt;h3 id=&quot;timestamp-dependence&quot;&gt;Timestamp Dependence&lt;/h3&gt;

&lt;p&gt;Valuation timestamps are provider assertions, and staleness uses
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;. Block producers can influence timestamps within protocol
bounds. Consumers must account for this uncertainty.&lt;/p&gt;

&lt;h3 id=&quot;decimal-normalization&quot;&gt;Decimal Normalization&lt;/h3&gt;

&lt;p&gt;Aggregation multiplies lower-precision signed values. Implementations must
enforce the numeric bounds in this ERC before normalization and use checked
arithmetic.&lt;/p&gt;

&lt;h3 id=&quot;privacy-and-commercial-sensitivity&quot;&gt;Privacy and Commercial Sensitivity&lt;/h3&gt;

&lt;p&gt;Methodology URIs, valuation timing, and provider behavior can reveal sensitive
fund or asset information. Deployments should avoid publishing confidential
documents or predictable private references on public chains.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8330</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8330</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
  </channel>
</rss>
